【问题标题】:Python socket receiving multiple messages at the same timePython socket 同时接收多条消息
【发布时间】:2019-08-19 20:15:08
【问题描述】:

我正在使用 python (3) 套接字进行 TCP/IP 聊天,并且我在 socket.send/socket.receive 对的多个实例中遇到了同样的问题。 举个例子:

每次服务器更新连接的客户端列表时,它首先发送一个字符串信号表示它即将这样做,逐项发送列表,然后发送另一个字符串信号表示它已完成。在客户端,我有一个接收消息并处理它们的线程,它有一个处理这个特定字符串信号的特定案例。在这种情况下,它会启动一个循环来接收客户端名称,直到它收到一个表明客户端列表结束的信号。

通常,但并非总是如此,客户端名称或字符串信号或两者都会混淆为单个消息。如果我有客户端 C1、C2、C3 并发送“结束”信号表示列表已完成,我的列表可能会显示如下内容:

C1C2
C3
“结束”

由于客户端只有这个线程和 GUI/主线程,而服务器端没有其他类型的消息混在一起(在用于侦听、处理客户端和 GUI/Main 的线程上),我假设它不是t 同步问题。我尝试在信号和列表之间添加不同大小的 time.sleep() 函数,但它仍然会发生。

在我使用此套接字聊天的整个过程中,我都注意到了这一点,但能够找出修复方法(通常使用 sleep()),但这个让我很难过。我是否在做一些根本上错误的事情,从而扰乱了我的消息发送和接收?如何保证每个 socket.send() 都发送一条数据?

【问题讨论】:

  • TCP 中没有消息。它是一个字节流协议。如果你想要消息,你必须自己实现它们。这里没有错误。
  • @user207421 抱歉,如果我不清楚,我了解协议的基本方面。您是否有任何建议/链接可以帮助操纵流来解决我的问题?
  • 是的,自己实现消息。我已经说过了。你需要一个基于 TCP 的应用协议。

标签: python multithreading sockets tcp chat


【解决方案1】:

TCP 是一种字节流协议。没有消息,只有一堆字节进来。你必须实现一个协议并缓冲接收到的数据,直到你知道你有一个完整的消息。

您可以使用内置的socket.makefile() 方法来实现面向行的协议。示例:

server.py

from socket import *

s = socket()
s.bind(('',5000))
s.listen(1)

while True:
    c,a = s.accept()
    print(f'connect: {a}')
    read  = c.makefile('r')
    write = c.makefile('w')

    with c,read,write:
        while True:
            data = read.readline()
            if not data: break
            cmd = data.strip()
            print(f'cmd: {cmd}')
            if cmd == 'LIST':
                write.write('C1\nC2\nC3\nDONE\n')
                write.flush()

    print(f'disconnect: {a}')

client.py

from socket import *

s = socket()
s.connect(('localhost',5000))
read = s.makefile('r',)
write = s.makefile('w')

def send(cmd):
    print(cmd)
    write.write(cmd + '\n')
    write.flush()

with s,read,write:
    send('TEST')
    send('LIST')
    while True:
        data = read.readline()
        if not data: break
        item = data.strip()
        if item == 'DONE': break
        print(f'item: {item}')
    send('OTHER')

服务器输出:

connect: ('127.0.0.1', 13338)
cmd: TEST
cmd: LIST
cmd: OTHER
disconnect: ('127.0.0.1', 13338)

客户端输出:

TEST
LIST
item: C1
item: C2
item: C3
OTHER

【讨论】:

  • 谢谢!所有这些对我来说都很新鲜,我什至没有想到使用 makefile 进行缓冲。
猜你喜欢
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 2020-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多