套接字碎片接收的数据[已解决]

时间:2019-09-06 17:29:05

标签: python python-3.x sockets tcp

我正在尝试创建某种客户端监视器,例如终端,以通过以太网从串行设备接收数据。我正在尝试将Socket与python结合使用,但是当我创建连接时就会出现问题。我应该只从服务器收到一条消息,然后我得到了整个消息,但分成两个数据包,如下所示:

预期消息:

DateTime

收到消息:

   b'-- VOID MESSAGE--'

我不知道这是否是缓冲区大小,解码或任何其他功能的问题

   b'-- VOID'
   b' MESSAGE--'

我已经尝试使用一些编解码器选项,例如UTF-8,UTF-16和ASCII,但是我仍然得到相同的结果。


今天,此功能帮助我解决了该问题。

import socket        

TCP_IP = '192.168.#.#'
TCP_PORT = ### 
BUFFER_SIZE = 1024
data1=' '

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

while(1):
    data = s.recv(BUFFER_SIZE)
    print(data.decode('ASCII'))


s.close()

感谢大家的帮助:)

3 个答案:

答案 0 :(得分:2)

如前所述-套接字就是这样工作的。 发送的数据可以拆分为多个块。因此,如果您想确定自己已收到发送的完整消息,则需要实现某种协议,其中一部分将包含消息的长度。例如:

  • 前四个字节(整数)代表消息的长度
  • 其他字节-消息内容

在这种情况下,发送消息的算法将类似于:

  • 计算邮件的长度
  • 写入具有消息长度的套接字整数(4个字节)
  • 写入消息的套接字内容

阅读算法:

  • 从套接字读取字节并将读取的数据写入累加器缓冲区
  • 从缓冲区读取前四个字节作为整数-这将是消息长度
  • 检查缓冲区长度是否大于或等于“ {消息长度} + 4”
  • 如果已读取所需的字节数,则会发送已发送的消息。
  • 从缓冲区中删除第一个“ {消息长度} + 4”个字节
  • 从第二点开始重复
  • 如果没有足够的字节来读取消息内容,请从第一点开始重复。

答案 1 :(得分:1)

一种解决方案是,如果可以忍受这些限制,请使用UDP代替TCP:

  1. 有大小限制,数据必须装入一个数据包
  2. UDP是“不可靠的”。

TCP连接传输一个字节流。 OTOH UDP传输单个数据报(消息)。如果发送方发送了N个数据报,则接收方应接收相同的N个数据报。也许是乱序,也许有些会丢失,但是每个数据报都独立于所有其他数据报。

关于限制,这些不是那么简单的问题。关于这些主题的信息很多,只需搜索即可。

最大大小取决于IPv4或IPv6,分段等因素,并且有最佳情况和最坏情况。通常,您可以假设一个以太网帧(用于所有标头+有效负载)绝对没有问题。

“不可靠”并不意味着转移的质量很糟糕。该网络应以“尽力而为”的方式工作。这意味着没有ACK,超时和重传。您可以不使用它,也可以在协议中添加简单的ACK。

答案 2 :(得分:0)

您可以使用此示例。

服务器代码:(从客户端读取)

#!/usr/bin/python3

from socket import socket, gethostname

s = socket()
host = gethostname()
port = 3399
s.bind((host, port))
s.listen(5)

while True:
    print("Listening for connections...")
    connection, addr = s.accept()

    try:
        buffer = connection.recv(1024)

        response = ''

        while buffer:                
            response += buffer.decode('ASCII')
            buffer = connection.recv(1024)

        print(response)
        connection.close()


    except KeyboardInterrupt:
        if connection:
            connection.close()
        break

客户代码:(发送消息)

#!/usr/bin/python3

from socket import socket, gethostname

s = socket()
host = gethostname()
port = 3399

s.connect((host, port))

print("Sending text..")

s.sendall(b'-- VOID MESSAGE--')

print("Done sending..")
s.close()