Python套接字服务器接收重复数据

3 投票
1 回答
3101 浏览
提问于 2025-04-17 21:28

我有一台树莓派,它在运行一个服务器,这个服务器可以和我笔记本上的另一个服务器进行通信。我是通过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的基础上加上一种“框架”协议。主要有两种方法可以做到这一点:

  1. 在每条消息前面加上消息的长度,然后读取那么多字节。

  2. 在每条消息之间放一个分隔符。

对于你的需求(发送没有换行的纯文本),第二种方法,用换行符作为分隔符,可能就足够了。你应该能想出怎么做,基本上就是重复以下步骤:

  1. 接收一些数据。
  2. 把这些数据添加到一个缓冲区。
  3. 查找换行符,并处理到那个点的缓冲区。重复这个步骤,直到没有更多的换行符。

如果你只是想打印数据,你可以把这些步骤简化为一个循环,从套接字接收数据,然后写入stdout

撰写回答