Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 1, 2011 10:05:18

alexx11
От:
Зарегистрирован: 2010-05-13
Сообщения: 208
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокет 2.5

Как сделать сокет что б socket.recv(bufsize) мог возвращать None, в случае если ничего нет.
setblocking(0) - Resource temporarily unavailable
setblocking(1) - зависает в ожидании.
settimeout(30) - тоже не то - через 30 секунд возбуждает ошибку: socket.timeout: timed out

Прикол в том что в 2.5 питоне, такой вызов крутится в цикле без всяких исключений в _fileobject.read():

while True:
data = self._sock.recv(recv_size)
if not data:
break
buffers.append(data)
И при любом раскладе, если не его заставить возвращать пустое значение, получаем фэйл!

Есть идеи?



Офлайн

#2 Фев. 1, 2011 10:30:36

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Сокет 2.5

> возбуждает ошибку: socket.timeout: timed out
это нормально, это значит никаких данных не пришло за указанный период, “так все и юзают”

можешь попробовать на селектах, может больше понравиться.

Офлайн

#3 Фев. 1, 2011 10:38:58

alexx11
От:
Зарегистрирован: 2010-05-13
Сообщения: 208
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокет 2.5

o7412369815963Я мог бы вообще обойтись send, recv. Пишу обёртку для другого класса, где _fileobject почти везде юзается, и вот такая делема, переписывать много и работать в 2.5 или переписывать мало и менять версию.



Офлайн

#4 Фев. 2, 2011 00:43:24

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокет 2.5

alexx11

Зависание происходит в ситуации когда размер данных кратен recv_size (например, посылаем 2048 байт, а recv_size 1024). Метод _sock.recv(recv_size) прочитает две порции данных, станет ждать еще, но ничего не получит. В итоге таймаут и исключение.

Есть несколько вариантов решения проблемы:

1. Если известно что пакет будет меньше некоторого размера, например 2 КБ, укажи recv_size = 2048

2. В заголовке пакета первые несколько байт указывают размер данных SIZE. Твой метод read() сперва читает несколько байт, узнает SIZE и затем читает остальное recv(SIZE).

3. Самый распостраненный. В конце пакета передается разделитель, который означает конец пакета. После чтения каждой порции данных проверяем что там в конце.

BUFSIZE = 4096
END = '\r\n\r\n'

def _recv(sock):
r = ''
while 1:
chunk = sock.recv(BUFSIZE)
r += chunk
if r.endswith(END):
return r[:-4]


def _send(sock, data):
sock.send(data + END)



Офлайн

#5 Фев. 2, 2011 01:06:52

alexx11
От:
Зарегистрирован: 2010-05-13
Сообщения: 208
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокет 2.5

dimabest
станет ждать еще, но ничего не получит. В итоге таймаут и исключение.
Я тоже так всегда считал, но интересно что думали когда 2.5 в релиз сдавали =\
dimabest
3. Самый распостраненный. В конце пакета передается разделитель, который означает конец пакета. После чтения каждой порции данных проверяем что там в конце.
Интересно. Но блин, это решение, в котором стандартную библиотеку надо допиливать, а мне это не нравится.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version