python socket recv висит [дубликат]

В JavaScript тип значения исключительно определяет, будет ли это значение присвоено копией значения или копией-копией.

Примитивные значения всегда назначаются / передаются по значению-копии :

  • null
  • undefined
  • строка
  • число
  • булево
  • символ в ES6

Соединение значения всегда назначаются / передаются по референс-копии

  • объектов
  • массивы
  • функция

Например

var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3

var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

В приведенном выше фрагменте, поскольку 2 является скалярным примитивом, a содержит одну начальную копию этого значения, а b присваивается другая копия значения , При изменении b вы никоим образом не изменяете значение в a.

Но оба c и d являются отдельными ссылками на одно и то же общее значение [1,2,3], которое является составная величина. Важно отметить, что ни c, ни d больше не «владеют» значением [1,2,3] - оба равны равным равноправным ссылкам на значение. Таким образом, при использовании любой ссылки для изменения (.push(4)) фактического общего значения array, это влияет только на одно общее значение, и обе ссылки будут ссылаться на вновь измененное значение [1,2,3,4].

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]

Когда мы выполняем присваивание b = [4,5,6], мы ничего не делаем, чтобы повлиять на a, где [1,2,3] все еще ссылается. Для этого b должен быть указателем на a, а не ссылкой на array, но в JS нет такой возможности

function foo(x) {
    x.push( 4 );
    x; // [1,2,3,4]

    // later
    x = [4,5,6];
    x.push( 7 );
    x; // [4,5,6,7]
}

var a = [1,2,3];

foo( a );

a; // [1,2,3,4]  not  [4,5,6,7]

Когда мы проходим аргумент a, он присваивает копию ссылки a на x. x и a - отдельные ссылки, указывающие на то же значение [1,2,3]. Теперь внутри функции мы можем использовать эту ссылку для мутации самого значения (push(4)). Но когда мы выполняем присваивание x = [4,5,6], это никоим образом не влияет на то, где указывается начальная ссылка a, - все еще указывает на значение (теперь измененное) [1,2,3,4].

Чтобы эффективно пройти составное значение (например, array) по копированию значения, вам нужно вручную сделать его копию, чтобы переданная ссылка не все еще указывала на оригинал. Например:

foo( a.slice() );

Составное значение (объект, массив и т. Д.), Которое может быть передано посредством reference-copy

function foo(wrapper) {
    wrapper.a = 42;
}

var obj = {
    a: 2
};

foo( obj );

obj.a; // 42

Здесь obj действует как обертка для скалярное примитивное свойство a. Когда передано foo(..), копия ссылки obj передается и устанавливается в параметр wrapper. Теперь мы можем использовать ссылку wrapper для доступа к общему объекту и обновить его свойство. После завершения функции obj.a вы увидите обновленное значение 42.

Источник

80
задан Thoreller 27 April 2010 в 06:51
поделиться

6 ответов

90
ответ дан akaihola 22 August 2018 в 16:09
поделиться
43
ответ дан Kimvais 22 August 2018 в 16:09
поделиться
  • 1
    Это не время ожидания recv (по крайней мере, когда я попробовал). Выключено только accept (). – Oren S 1 June 2011 в 12:40
  • 2
    Кажется, что socket.recv () для меня отлично подходит после установки socket.settimeout () точно так, как предполагалось. Я это делаю? Может ли кто-нибудь еще подтвердить это? – Aeonaut 23 October 2011 в 04:20
  • 3
    @Aeonaut Я думаю, что это время вне recv () большую часть времени, но есть состояние гонки. В socket.recv () Python (2.6) вызывает select / poll внутри с таймаутом, а затем recv () вызывается сразу после. Поэтому, если вы используете блокирующий сокет, и между этими двумя вызовами происходит сбой другой конечной точки, вы можете бесконечно зависать на recv (). Если вы используете неблокирующий сокет, python не вызывает select.select внутри, поэтому я думаю, что ответ Даниэля Штуцбаха правильный. – emil.p.stanchev 4 August 2012 в 09:51
  • 4
    На самом деле, я, вероятно, неправильно понял, когда select () возвращается, поэтому, пожалуйста, поцарапайте предыдущий комментарий. Руководство Beej's говорит, что приведенное выше является допустимым способом реализации тайм-аута в recv: beej.us/guide/bgnet/output/html/singlepage/… , поэтому я буду доверять, является официальным источником. – emil.p.stanchev 4 August 2012 в 10:42
  • 5
    Я не уверен, почему решение, использующее select, предпочтительнее, когда это решение является одним лайнером (проще поддерживать, меньше рисковать при неправильном использовании) и использует select под капотом (реализация такая же, как ответ @DanielStuzbach) , – Trevor Boyd Smith 21 November 2017 в 17:26

попробуйте это, он использует базовый C.

timeval = struct.pack('ll', 2, 100)

s.setsockopt(socket.SOL_SOCKET,SO_RCVTIMEO, timeval)
0
ответ дан Miriam Farber 22 August 2018 в 16:09
поделиться
  • 1
    Это замечательно, так как позволяет устанавливать разные значения для тайм-аута отправки и возврата с помощью SO_RCVTIMEO и SO_SNDTIMEO. – jtpereyda 30 June 2018 в 20:59

Вы можете установить время ожидания до получения ответа и после получения ответа установить его обратно на None:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
9
ответ дан noriko 22 August 2018 в 16:09
поделиться

Как упоминалось, оба select.select() и socket.settimeout() будут работать.

Обратите внимание, что вам может потребоваться дважды settimeout для ваших нужд , например

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()

# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)
20
ответ дан ubershmekel 22 August 2018 в 16:09
поделиться
  • 1
    Я думаю, что он получает то же самое, что и я, независимо от того, как ты ткнул и подталкивал эту функцию. Я пробовал 2 или 4 таймаута сейчас, и он все еще зависает. settimeout висит также. – Casey Daniel 30 September 2014 в 23:19
  • 2
    Поскольку вы вызываете .settimeout() более одного раза, вы можете на первый взгляд вызвать метод setdefaulttimeout(). – mvarge 17 November 2016 в 22:40

Тайм-аут, который вы ищете, - это тайм-аут сокета подключения, а не основной сокет, если вы реализуете серверную сторону. Другими словами, есть еще один тайм-аут для объекта сокета соединения, который является выходом метода socket.accept(). Поэтому:

sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5)    # This is the one that affects recv() method.
connection.gettimeout()     # This should result 5
sock.gettimeout()           # This outputs None when not set previously, if I remember correctly.

Если вы реализуете клиентскую сторону, это будет просто.

sock.connect(server_address)
sock.settimeout(3)
1
ответ дан V123 22 August 2018 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: