Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
同时接收多条消息的Python套接字_Python_Multithreading_Sockets_Tcp_Chat - Fatal编程技术网

同时接收多条消息的Python套接字

同时接收多条消息的Python套接字,python,multithreading,sockets,tcp,chat,Python,Multithreading,Sockets,Tcp,Chat,我正在与python(3)socket进行TCP/IP聊天,我在socket.send/socket.receive对的多个实例上遇到了相同的问题。 例如: 每次服务器更新已连接客户端的列表时,它首先发送一个字符串,表示它将要更新,然后逐项发送列表,再发送另一个字符串信号,表示已完成。在客户端,我有一个线程来接收和处理消息,它有一个特定的案例来处理这个特定的字符串信号。在这种情况下,它启动一个循环来接收客户机名称,直到它接收到一个表示客户机列表已结束的信号 然而,客户机名称或字符串信号或两者都作

我正在与python(3)socket进行TCP/IP聊天,我在socket.send/socket.receive对的多个实例上遇到了相同的问题。 例如:

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

然而,客户机名称或字符串信号或两者都作为一条消息混合在一起,这是经常发生的,尽管并非总是如此。如果我有客户机C1、C2、C3,并发送信号“结束”表示列表已完成,我的列表可能会显示如下内容:

C1C2
C3
“结束”

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


我在使用这个套接字聊天的整个过程中都注意到了这一点,但我一直能够找到修复方法(通常是使用sleep()),但这一点让我感到困惑。我是否做了一些根本错误的事情,把我的信息发送和接收搞得一团糟?如何保证在每个套接字上发送一段数据。send()?

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}')
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')
client.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}')
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
客户端输出:

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

TCP中没有消息。这是一个字节流协议。如果您想要消息,您必须自己实现它们。这里没有错误。@user207421如果我不清楚,很抱歉,我理解协议的基本方面。您是否有任何建议/链接可以帮助处理流以解决我的问题?是的,您自己实现消息。我已经说过了。您需要TCP上的应用程序协议。谢谢!所有这些对我来说都是非常新的,使用makefile进行缓冲的想法甚至没有在我脑海中出现。