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

时间:2014-03-09 01:28:14

标签: python sockets

我有一个运行服务器的覆盆子,可以与笔记本电脑上的服务器通信。我通过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))

在客户端代码中设置print语句会产生(x,y,z),这是预期的输出。但是,在服务器上接收数据后,它将以模式显示:

(x,y,z)(x,y,z)
(x,y,z)
(x,y,z)
(x,y,z)(x,y,z)
...

为什么数据是重复的?它是TCP的属性吗?如果是这样,我怎么能反击这个来接收数据作为我最初发送的字符串。

1 个答案:

答案 0 :(得分:2)

TCP将数据作为流发送。您可以将数据写入该流,并且可以从该流接收数据。重要的是,虽然可以是一个发送对应于一个接收的情况,但根本不能保证是这种情况。你可以发送一个大块并以一堆较小的块接收它,或者你可以发送一堆较小的块并接收一大块,或者介于两者之间的任何东西。你处于后一种情况。

要解决此问题,您需要在TCP之上层叠某种成帧协议。您可以采用以下两种主要方式:

  1. 使用消息的长度为每条消息添加前缀,然后读取那么多字节。

  2. 在每封邮件之间加上分隔符。

  3. 出于您的目的(发送没有换行符的纯文本),后者用换行符作为分隔符可能没问题。您可以想出如何做到这一点,但实际上,重复这样做:

    1. 接收一些数据。
    2. 将该数据附加到缓冲区。
    3. 搜索换行符并处理缓冲区。重复此步骤,直到没有新行。
    4. 如果您正在进行打印,则可以通过循环替换所有内容,从套接字接收然后写入stdout