处理以换行符结尾的套接字数据

新手上路,请多包涵

处理套接字连接的最佳方法是什么,我需要 var data 以换行符结束 \n ?我正在使用下面的代码,但有时 tcp 数据包被 分块 并且需要很长时间才能匹配 data.endswith("\n") 。我也尝试过其他方法,比如保存最后一行,如果它没有以 \n 结尾,并将其附加到 data 下一个循环。但这也不起作用,因为多个数据包被分块并且第一部分和第二部分不匹配。我无法控制另一端,它基本上发送以 \r\n 结尾的多行。

欢迎任何建议,因为我对套接字连接了解不多。

 def receive_bar_updates(s):
    global all_bars
    data = ''
    buffer_size = 4096
    while True:
        data += s.recv(buffer_size)
        if not data.endswith("\n"):
            continue
        lines = data.split("\n")
        lines = filter(None, lines)
        for line in lines:
            if line.startswith("BH") or line.startswith("BC"):
                symbol = str(line.split(",")[1])
                all_bars[symbol].append(line)
                y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
                y.start()
        data = ""

“ _正常_”示例 data

 line1\r\n
line2\r\n
line3\r\n

分块 示例 data

 line1\r\n
line2\r\n
lin

原文由 Pedro Lobito 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 723
2 个回答

如果你有一个原始输入,你想按行处理,那么 io 模块是你的朋友,因为它会按行进行数据包的低级组装。

你可以使用:

 class SocketIO(io.RawIOBase):
    def __init__(self, sock):
        self.sock = sock
    def read(self, sz=-1):
        if (sz == -1): sz=0x7FFFFFFF
        return self.sock.recv(sz)
    def seekable(self):
        return False

它比 endswith('\n') 更健壮,因为如果一个数据包包含嵌入的换行符( 'ab\ncd' ),io 模块将正确处理它。您的代码可能会变成:

 def receive_bar_updates(s):
    global all_bars
    data = ''
    buffer_size = 4096
    fd = SocketIO(s)  # fd can be used as an input file object

    for line in fd:
        if should_be_rejected_by_filter(line): continue # do not know what filter does...
        if line.startswith("BH") or line.startswith("BC"):
            symbol = str(line.split(",")[1])
            all_bars[symbol].append(line)
            y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
            y.start()

原文由 Serge Ballesta 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 socket.socket.makefile() 将套接字包装在一个实现 文本 I/O 的类中。它处理缓冲、字节和字符串之间的转换,并允许您遍历行。记住刷新任何写入。

例子:

 #!/usr/bin/env python3
import socket, threading, time

def client(addr):
    with socket.create_connection(addr) as conn:
        conn.sendall(b'aaa')
        time.sleep(1)
        conn.sendall(b'bbb\n')
        time.sleep(1)
        conn.sendall(b'cccddd\n')
        time.sleep(1)
        conn.sendall(b'eeefff')
        time.sleep(1)
        conn.sendall(b'\n')
        conn.shutdown(socket.SHUT_WR)
        response = conn.recv(1024)
        print('client got %r' % (response,))

def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as listen_socket:
        listen_socket.bind(('localhost', 0))
        listen_socket.listen(1)
        addr = listen_socket.getsockname()
        threading.Thread(target=client, args=(addr,)).start()
        conn, _addr = listen_socket.accept()
        conn_file = conn.makefile(mode='rw', encoding='utf-8')
        for request in conn_file:
            print('server got %r' % (request,))
        conn_file.write('response1\n')
        conn_file.flush()

if __name__ == '__main__':
    main()

 $ ./example.py
server got 'aaabbb\n'
server got 'cccddd\n'
server got 'eeefff\n'
client got b'response1\n'
$

原文由 M. Leonhard 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题