Форум сайта python.su
Привет сообществу!
У меня возникла проблема … вроде кусками нашел информацию, но не системно. Скажите пожалуйста, при сокетном взаимодействии строка передается разом, или может передаваться порциями? То есть, достаточно для принятия строки сделать так:
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
Офлайн
SteshСоветую почитать книгу “Foundations of Python Network Programming 2nd Edition (Brandon Rhodes, John Goerze)”
вроде кусками нашел информацию, но не системно
SteshИли же. Правда, лучше посмотрите в книге пример recv_all() (вроде).
То есть, достаточно для принятия строки сделать так:
s = client_socket.recv(len_)
Или же:
SteshНе должно, сколько сейчас есть, столько и вернется. Но лучшим ответом на такой вопрос будет эксперимент.
Может ли в строку при передаче попасть мусор, если я передаю строку меньшего размера, чем принимаю
Офлайн
Спасибо большое, reclosedev!
Сижу разбираюсь) Конечно передача может происходить порциями) Стоило самому поиграться)
А вот насчет мусора…мусор проходит. не всегда, но почему то проходит. Код в три строчки, просто эксперимент, и все равно просачивается всякое, ничего сложного не передаю, только строчку.
Спасибо за книгу, по примерам точно пробегусь.
Офлайн
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 # конкатинирую полученную порцию строки и текущую
Офлайн
так нельзя,
сетевые пакеты могут слипнуться в один, так и разорваться на несколько в любом месте,
в данном случае нужно (как вариант) размер данных упаковывать например в 4 байта, а на приеме эти 4 байта обратно в строку. http://docs.python.org/2/library/struct.html (либо в строку, но определиться с длинной)
если открытый сокет держать не обязательно (чаще всего), то можно без передачи размера - получать все данные пока сокет не закроется, а отправитель соответственно должен зарывать сокет после отправки всех данных.
Отредактировано o7412369815963 (Апрель 8, 2013 01:13:04)
Офлайн
o7412369815963, спасибо большое за модуль struct! Находил пару статей в сети, где его использовали, но не придавал этому значения…там еще что-то с Pickle было, нужно и про него что-нибудь прочитать.
Спасибо за помощь, о таких тонкостях не знал(а скорее всего это не тонкости), когда на “плюсах” делал клиент-сервер, упаковку не производил. Может и там что-то такое есть.
Офлайн
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) ...
Офлайн
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
Офлайн
Не могло там быть такого примера.
Какой смысл два раза проверять data_len > len(data) и if data_len - len(data) == 0: break? И если нужно прочесть определенную длину, то client_socket.recv(1024) может вернуть больше чем нужно, тут должно быть именно data_len - len(data).
SteshДумаю, здесь было бы неправильным давать ссылки на пиратские ресурсы, но гугл по запросу
Буду искать полную версию.
Офлайн