问题描述
我正在使用python(3)套接字进行TCP / IP聊天,并且在socket.send / socket.receive对的多个实例上遇到了相同的问题。
例如:
I'm making a TCP/IP chat with python (3) sockets, and I have been having the same problem over multiple instances of socket.send/socket.receive pairs. As an example:
每次服务器更新连接的客户端列表时,它首先发送一个字符串,表示即将这样做,然后发送列表逐项发送,并发送另一个字符串信号表示已完成。在客户端,我有一个线程来接收消息并处理它们,并且它具有处理此特定字符串信号的特定情况。在这种情况下,它开始循环以接收客户端名称,直到收到表示客户端列表已结束的信号。
Everytime the server updates the list of connected clients, it first sends a string signaling that it is about to do so, sends the list item by item, and sends another string signal to say it is done. Client-side, I have a thread that receives messages and handles them, and it has a specific case for dealing with this specific string signal. In this case, it starts a loop to receive client names until it receives a signal saying that the list of clients is over.
通常(尽管并非总是如此),客户端名称或字符串信号或两者混为一谈。如果我有客户C1,C2,C3,并发送 over信号说列表已完成,则我的列表可能显示如下内容:
Often, though not always, either the client names or the string signals or both get mixed up as a single-message, however. If I have clients C1, C2, C3 and send the signal "over" to say the list is done, my list might display something like:
由于客户端-端只有这个线程和GUI / Main线程,而服务器端没有其他类型的消息混杂在一起(在用于侦听,处理客户端和GUI / Main的线程上),我假设这不是同步问题。我曾尝试在信号和列表之间添加大小可变的time.sleep()函数,但仍然会发生。
Since client-side only has this thread and GUI/Main thread, and server-side no other type of message gets mixed up (on threads for listening, handling clients and GUI/Main), I'm assuming it isn't a synchronization issue. I've tried adding time.sleep() funcs of varied size between the signals and the list, but it still happens.
我在整个使用过程中都注意到了这一点。这个套接字聊天,但是能够找出解决方法(通常使用sleep()),但是这个让我很困惑。我是否在做一些根本上错误的事情,弄乱了我发送和接收的消息?如何保证在每个socket.send()处发送单个数据?
I have noticed this throughout my entire experience with this socket chat, but had been able to figure out fixes (usually with sleep()), but this one has me stumped. Am I doing something fundamentally wrong that is messing up my sending and receiving of messages? How can I guarantee that a single piece of data will be sent at each socket.send()?
推荐答案
TCP是一个字节流协议。没有消息,只有一堆字节进来。您必须实现协议并缓冲接收到的数据,直到知道完整的消息为止。
TCP is a byte-stream protocol. There are no messages but just a bunch of bytes coming in. You must implement a protocol and buffer the data received until you know you have a complete message.
您可以使用内置的 socket.makefile()
方法来实现面向行的协议。示例:
You can use the built-in socket.makefile()
method to implement a line-oriented protocol. Example:
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
这篇关于Python套接字同时接收多个消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!