как получить сокет-сообщение с пустыми данными? - PullRequest
1 голос
/ 29 июля 2010

у меня есть клиент сокетов и сервер сокетов.

(сервер работает на python и работает синхронно.)

иногда клиенты отправляют пустую строку.Я должен определить эту ситуацию и вернуть ответ.

с этим кодом сервер просто продолжает ждать, а клиент ничего не получает взамен, если только он не отправляет что-то «толстое»;)

как я могу захватить пустойсообщение?это вообще возможно?

это мой код сервера:

import SocketServer

def multi_threaded_socket_server():

    class MyRequestHandler(SocketServer.BaseRequestHandler):
        def handle(self):
            while True:
                print 'waiting for client calls...'
                received = self.request.recv( PACKET_SIZE )
                (handle request... )

Ответы [ 5 ]

6 голосов
/ 09 августа 2015
  • В TCP нет такой вещи, как пустое сообщение, поэтому ноль означает одноранговое разъединение.
  • В UDP нет такого понятия, как одноранговое разъединение, поэтому ноль означает пустую дейтаграмму.

Когда вы описываете многопоточный сервер сокетов, вам кажется, что это TCP, и в этом случае ваше требование не имеет смысла. Вы не можете отправить пустое сообщение по TCP. Вам придется использовать наложенный протокол для всего.

0 голосов
/ 10 марта 2016

* Предполагается, что вы отправляете пакеты с модулем сокета python с TCP / IP, например:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip_in, port_in))

Вы не можете отправить пустое сообщение:

sock.sendall(bytes("", 'ascii'))

Строки, отправленные с TCP / IP, заканчиваются нулем и выглядят примерно так:

IP packing | TCP packing | string | null ascii character (0x00 in hex)

Таким образом, отправка "" приведет к:

IP packing | TCP packing | 0x00

, который TCP-сервер будет интерпретировать как разъединение, и обработчик не будет обслуживать запрос.

Чтобы отправить «пустое сообщение», которое будет обрабатывать сервер, используйте что-то вроде:

sock.sendall(bytes("\00", 'ascii'))

, который отправляет пакет, который выглядит следующим образом:

IP packing | TCP packing | 0x00 | 0x00

и обработка будет выглядеть примерно так:

data = str(self.request.recv(1024), 'ascii')
# data = ""

Хотя все tcp-пакеты используют 32 бита данных независимо от того, используются они или нет, поэтому отправка одного нулевого символа на самом деле не будет значительным преимуществом для производительности.

0 голосов
/ 29 июля 2010

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

Разработка протокола, который включает способ определить, было ли получено полное сообщение. Распространенными способами являются отправка сообщения первым или использование специальной последовательности в конце, указывающей, что сообщение завершено. Также обратите внимание, что метод sendall () сокета будет отправлять все байты сообщения.

Примеры:

sendall('\x05Hello')  # length first
sendall('Hello\x00')  # nul-termination

Для получения, буфер recv () вызывает до полного сообщения.

Алгоритм получения (нерабочий код):

class Handler:

  def __init__(self):
    self.buffer = ''

  def handler(self):
    while True:
      msg = self.get_msg()
      if not msg: break
      process msg

  def get_msg(self):
    if complete message not at the beginning of buffer:
      chunk = recv(1000)
      if not chunk: return '' # socket closed
      buffer += chunk
    remove message from beginning of buffer...update buffer
    return message
0 голосов
/ 19 марта 2014

Как уже говорилось ранее, recv () возвращение 0 означает «отключение», поэтому вы не можете получить сообщение длиной 0.

Однако вы можете получить сообщение TCP, которое кажется пустым, если вы посмотрите на него только как на строку, если фактически получен пакет, начинающийся с символа '\ 0'.

Вы можете обращаться с этим угловым корпусом как:

received = self.request.recv( PACKET_SIZE )
if received[0]=='\x00':
    <handle empty packet>
0 голосов
/ 29 июля 2010

Если пустая строка означает 0 байтов, библиотека сокетов на стороне клиента может игнорировать ее, поскольку пакет с 0 байтами данных является пакетом отключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...