Найти - Пользователи
Полная версия: Порции или сразу?
Начало » Network » Порции или сразу?
1 2
Stesh
Привет сообществу!

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

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

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

s = client_socket.recv(len_)

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

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

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

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

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

приведи код
Stesh
Сейчас вроде бы исправил) Делал следующее: передавал длину строки, после чего ее саму. получал длину строки, после чего порциями(по 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, если загляните, напишите пожалуйста, все ли тут нормально на первый взгляд? (тестировал около десятка раз, пока все спокойно)
o7412369815963
так нельзя,
сетевые пакеты могут слипнуться в один, так и разорваться на несколько в любом месте,
в данном случае нужно (как вариант) размер данных упаковывать например в 4 байта, а на приеме эти 4 байта обратно в строку. http://docs.python.org/2/library/struct.html (либо в строку, но определиться с длинной)

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

Спасибо за помощь, о таких тонкостях не знал(а скорее всего это не тонкости), когда на “плюсах” делал клиент-сервер, упаковку не производил. Может и там что-то такое есть.
reclosedev
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)
...
Stesh
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 на глаза попалась) Буду искать полную версию.
reclosedev
Не могло там быть такого примера.
Какой смысл два раза проверять 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” выдает первую ссылку.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB