Python套接字服务器接收重复数据
我有一台树莓派,它在运行一个服务器,这个服务器可以和我笔记本上的另一个服务器进行通信。我是通过Python里的简单套接字连接来实现的。
像这样:
服务器
HOST = "192.168.0.115"
PORT = 5001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
while conn:
data = conn.recv(1024)
print data
if not data:
break
conn.close()
客户端
__init__(self,addr,port,timeout):
self.addr = addr
self.port = port
self.timeout = timeout
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.addr,self.port))
#in a different file the call to send is made, passes list object as a parameter
send(self,data):
if self.socket:
self.socket.send(str(data))
在客户端代码里设置一个打印语句,结果显示为 (x,y,z),这是我预期的输出。不过,当服务器接收到数据时,它的显示方式却是这样的:
(x,y,z)(x,y,z)
(x,y,z)
(x,y,z)
(x,y,z)(x,y,z)
...
为什么接收到的数据会出现重复?这是TCP协议的特性吗?如果是的话,我该怎么做才能把数据作为一个完整的字符串接收,就像我一开始想要的那样。
1 个回答
3
TCP是一种数据传输方式,它把数据当作一个流来发送。你可以把数据写入这个流,也可以从这个流中接收数据。重要的是,虽然一个发送的消息可能对应一个接收的消息,但这并不是一定的。你可能会发送一个大块数据,却接收到几小块;或者发送几小块数据,却接收到一大块;甚至还有其他的组合情况。你现在正处于后者的情况。
要解决这个问题,你需要在TCP的基础上加上一种“框架”协议。主要有两种方法可以做到这一点:
在每条消息前面加上消息的长度,然后读取那么多字节。
在每条消息之间放一个分隔符。
对于你的需求(发送没有换行的纯文本),第二种方法,用换行符作为分隔符,可能就足够了。你应该能想出怎么做,基本上就是重复以下步骤:
- 接收一些数据。
- 把这些数据添加到一个缓冲区。
- 查找换行符,并处理到那个点的缓冲区。重复这个步骤,直到没有更多的换行符。
如果你只是想打印数据,你可以把这些步骤简化为一个循环,从套接字接收数据,然后写入stdout
。