Несколько записей обрабатываются как одна - PullRequest
1 голос
/ 01 апреля 2012

У меня проблема с этим кодом.Я открываю сокет, затем слушаю его с помощью цикла while.Я отправляю данные из php-скрипта с

socket_write($sock, $test, $len);

Это работает очень хорошо, но когда я посылаю несколько записей подряд, скрипт Python обрабатывает некоторые записи как одну запись.

import socket

HOST = 'localhost' # the host
PORT = 12126 # the port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
while 1:
  s.listen(0)
  conn, addr = s.accept()
  print 'Connected by', addr
  while 1:
      data = conn.recv(1024)
      if not data: break
conn.close()

Я ищу способ прослушать этот порт и получать одну запись за другой.

Ответы [ 2 ]

3 голосов
/ 02 апреля 2012

Это не так, как работают сокеты. Входят байты и выходят байты, но должен быть какой-то другой механизм, чтобы сказать вам, насколько велико сообщение. Если вы отправите 50 байтов, затем еще 75 байтов, затем 20 байтов на одном конце сокета и затем вызовите recv (100), вы можете получить от 1 до 100 байтов из блокирующего сокета. Вы несете ответственность за буферизацию recv, пока не получите полное сообщение, и вам необходимо определить, что такое полное сообщение. Некоторые варианты:

  1. Отправка сообщений фиксированной длины.
  2. Отправьте фиксированное количество байтов, представляющих длину сообщения, затем сообщение.
  3. Разделяйте сообщения с помощью сторожевого байта.

Вот пример класса для буферизации полученных данных с использованием байта стража:

import socket

class Client(object):

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

    def connect(self,address):
        self.buffer = ''
        self.sock = socket.socket()
        self.sock.connect(address)

    def get_msg(self):
        '''Append raw data to buffer until sentinel is found,
           then strip off the message, leaving the remainder
           in the buffer.
        '''
        while not '\n' in self.buffer:
            data = self.sock.recv(4096)
            if not data:
                return ''
            self.buffer += data
        sentinel = self.buffer.index('\n') + 1
        msg,self.buffer = self.buffer[:sentinel],self.buffer[sentinel:]
        return msg

    def close(self):
        self.sock.close()

if __name__ == '__main__':
    c = Client()
    c.connect((HOST,PORT))
    while True:
        msg = c.get_msg()
        if not msg:
            break
        print repr(msg)
    c.close()
1 голос
/ 01 апреля 2012

Не думаю, что так работают сокеты Unix. Системный вызов recv может вернуть столько данных, сколько ему нужно, потенциально упаковывая сообщения в буфере вместе. http://linux.die.net/man/2/recv

Типичный способ достичь желаемого - использовать протокол с разделителями между каждым сообщением. Например, HTTP и SMTP используют новые строки для разделения каждой части сообщения.

В Python вы можете использовать что-то вроде этого:

for message in data.split('\n'):
    do_stuff(message)

http://docs.python.org/howto/sockets.html

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