Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 6, 2013 14:45:58

Stesh
Зарегистрирован: 2013-03-30
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Порции или сразу?

Привет сообществу!

У меня возникла проблема … вроде кусками нашел информацию, но не системно. Скажите пожалуйста, при сокетном взаимодействии строка передается разом, или может передаваться порциями? То есть, достаточно для принятия строки сделать так:

s = client_socket.recv(len_)

Или же:

s = ''
# , где s - строка, len_ - длина строки
while len(s)<len_:
        s    += client_socket.recv(len_) 

Так же еще один вопрос. Может ли в строку при передаче попасть мусор, если я передаю строку меньшего размера, чем принимаю(извиняюсь за непонятность изъяснения, попробую примером):

# Передаю
client_socket.send(s) # s = 'Hello'
# Получаю
s  = client_socket.recv(1024)
# Тоесть переданная строка равна 5 символам, а получаю 1024

Заранее спасибо. С Уважением, Стешенко А.

Офлайн

#2 Апрель 6, 2013 16:43:06

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Порции или сразу?

Stesh
вроде кусками нашел информацию, но не системно
Советую почитать книгу “Foundations of Python Network Programming 2nd Edition (Brandon Rhodes, John Goerze)”
Stesh
То есть, достаточно для принятия строки сделать так:

s = client_socket.recv(len_)

Или же:
Или же. Правда, лучше посмотрите в книге пример recv_all() (вроде).

Stesh
Может ли в строку при передаче попасть мусор, если я передаю строку меньшего размера, чем принимаю
Не должно, сколько сейчас есть, столько и вернется. Но лучшим ответом на такой вопрос будет эксперимент.

Офлайн

#3 Апрель 6, 2013 16:54:48

Stesh
Зарегистрирован: 2013-03-30
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Порции или сразу?

Спасибо большое, reclosedev!

Сижу разбираюсь) Конечно передача может происходить порциями) Стоило самому поиграться)
А вот насчет мусора…мусор проходит. не всегда, но почему то проходит. Код в три строчки, просто эксперимент, и все равно просачивается всякое, ничего сложного не передаю, только строчку.
Спасибо за книгу, по примерам точно пробегусь.

Офлайн

#4 Апрель 6, 2013 23:38:12

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9902
Репутация: +  855  -
Профиль   Отправить e-mail  

Порции или сразу?

Stesh
Может ли в строку при передаче попасть мусор, если я передаю строку меньшего размера
если там данных приходит меньше, чем запрашиваешь, то в буфер записываются только эти данные

Stesh
А вот насчет мусора…мусор проходит. не всегда, но почему то проходит.
значит, либо посылаешь ещё что-то, либо принятые данные просматриваешь как-то не так

приведи код



Офлайн

#5 Апрель 7, 2013 13:28:40

Stesh
Зарегистрирован: 2013-03-30
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Порции или сразу?

Сейчас вроде бы исправил) Делал следующее: передавал длину строки, после чего ее саму. получал длину строки, после чего порциями(по 1024 байта) саму строку. Сейчас попробую проиллюстрировать:

# Передача
socket.send(str(len(data))) # передача длины строки
socket.send(data)              # передача самой строки
# Получение
data_len, data = long(client_socket.recv(1024)), '' # получаю длину строки, объявляю и определяю       # пустую строку
while data_len > len(data): # пока длина текущей строки меньше ее переданной длины
        if data_len - len(data) == 0: break
        read = client_socket.recv(1024) # считываю в буфер
        if not read: break # увидел в туториале, видимо если ничего не пришло, пройдет это условие
        data += read # конкатинирую полученную порцию строки и текущую

Надеюсь тут все правильно. py.user.next, если загляните, напишите пожалуйста, все ли тут нормально на первый взгляд? (тестировал около десятка раз, пока все спокойно)

Офлайн

#6 Апрель 8, 2013 01:11:29

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

Порции или сразу?

так нельзя,
сетевые пакеты могут слипнуться в один, так и разорваться на несколько в любом месте,
в данном случае нужно (как вариант) размер данных упаковывать например в 4 байта, а на приеме эти 4 байта обратно в строку. http://docs.python.org/2/library/struct.html (либо в строку, но определиться с длинной)

если открытый сокет держать не обязательно (чаще всего), то можно без передачи размера - получать все данные пока сокет не закроется, а отправитель соответственно должен зарывать сокет после отправки всех данных.

Отредактировано o7412369815963 (Апрель 8, 2013 01:13:04)

Офлайн

#7 Апрель 8, 2013 11:29:14

Stesh
Зарегистрирован: 2013-03-30
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Порции или сразу?

o7412369815963, спасибо большое за модуль struct! Находил пару статей в сети, где его использовали, но не придавал этому значения…там еще что-то с Pickle было, нужно и про него что-нибудь прочитать.

Спасибо за помощь, о таких тонкостях не знал(а скорее всего это не тонкости), когда на “плюсах” делал клиент-сервер, упаковку не производил. Может и там что-то такое есть.

Офлайн

#8 Апрель 8, 2013 18:58:00

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Порции или сразу?

Stesh, повторюсь, в книге все это есть. И про получение порциями и про struct (пример на 78 стр.):

...
format = struct.Struct('!I')
def recvall(sock, length):
    data = '' 
    while len(data) < length: 
        more = sock.recv(length - len(data)) 
        if not more: 
            raise EOFError('socket closed %d bytes into a %d-byte message' 
                            % (len(data), length)) 
        data += more 
    return data 
 
def get(sock): 
    lendata = recvall(sock, format.size) 
    (length,) = format.unpack(lendata) 
    return recvall(sock, length) 
 
def put(sock, message):
    sock.send(format.pack(len(message)) + message)
...

Офлайн

#9 Апрель 8, 2013 19:40:29

Stesh
Зарегистрирован: 2013-03-30
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Порции или сразу?

reclosedev, спасибо, снова выручаешь) Дело в том, что я вбил в гугл название книги. Она лежала на http://books.google.ru/ в урезанной версии. Я посмотрел все примеры, на чем-то останавливался по тексту. В общем, там было только 4 главы)..как раз упаковку они не затрагивают. Но книга пригодилась и на этих первых главах, именно оттуда(если не ошибаюсь, 38 страница) я взял следующую конструкцию:

while data_len > len(data):
        if data_len - len(data) == 0: break
        read = client_socket.recv(1024)
        if not read: break
        data += read

Дальше как раз в оглавлении Pickle на глаза попалась) Буду искать полную версию.

Офлайн

#10 Апрель 8, 2013 20:00:56

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Порции или сразу?

Не могло там быть такого примера.
Какой смысл два раза проверять data_len > len(data) и if data_len - len(data) == 0: break? И если нужно прочесть определенную длину, то client_socket.recv(1024) может вернуть больше чем нужно, тут должно быть именно data_len - len(data).

Stesh
Буду искать полную версию.
Думаю, здесь было бы неправильным давать ссылки на пиратские ресурсы, но гугл по запросу
“Foundations of Python Network Programming, Second Edition” выдает первую ссылку.

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version