Python 套接字正在从服务器接收不一致的消息

Python Socket is receiving inconsistent messages from Server

所以我对网络还很陌生,我使用 Python Socket 库连接到传输位置数据流的服务器。

这是使用的代码。

import socket

BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((gump.gatech.edu, 756))

try:
    while (1):
        data = s.recv(BUFFER_SIZE).decode('utf-8')
        print(data)
except KeyboardInterrupt:
    s.close()

问题是数据以不一致的形式到达。

大多数时候它以正确的形式到达,如下所示:

2016-01-21 22:40:07,441,-84.404153,33.778685,5,3

但有时它会像这样分成两行到达:

2016-01-21

22:40:07,404,-84.396004,33.778085,0,0

有趣的是,当我使用 Putty 建立到服务器的原始连接时,我只得到正确的形式,而没有得到拆分。所以我想一定有什么事情在分裂消息。或者 Putty 正在做的事情总是 assemble 正确。

我需要的是变量 data 始终包含正确的行。知道如何实现吗?

编辑socket.recv() 正在阻塞,就像其他人所说的那样,每次调用该方法时都不会得到准确的一行。因此,结果是,套接字正在等待数据,获取它可以获取的数据,然后 returns。当你打印这个时,由于 python 的默认结束参数,你可能会得到比你预期更多的换行符。因此,要从您的服务器获取原始内容,请使用:

import socket 
BUFFER_SIZE = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('gump.gatech.edu', 756)) 
try: 
    while (1):   
        data=s.recv(BUFFER_SIZE).decode('utf-8')
        if not data: break
        print(data, end="") 
except KeyboardInterrupt: 
    s.close()

最好将套接字视为连续的数据流,它可能以点点滴滴的形式到达,也可能像洪水一样涌来。

特别是,将数据分解成它应该包含的 "records" 是接收者的工作,套接字不知道如何为你做这件事。这里记录的是行,所以你必须自己读取数据并拆分成行。

您不能保证单个 recv 将是一个完整的行。可能是:

  • 只是一行的一部分;
  • 或多行;
  • 或者,很可能是几行和另一部分行。

试试这样的东西:(未经测试)

# we'll use this to collate partial data
data = ""

while 1:
    # receive the next batch of data
    data += s.recv(BUFFER_SIZE).decode('utf-8')

    # split the data into lines
    lines = data.splitlines(keepends=True)

    # the last of these may be a part line
    full_lines, last_line = lines[:-1], lines[-1]

    # print (or do something else!) with the full lines
    for l in full_lines:
        print(l, end="")

    # was the last line received a full line, or just half a line?
    if last_line.endswith("\n"):
        # print it (or do something else!)
        print(last_line, end="")

        # and reset our partial data to nothing
        data = ""
    else:
        # reset our partial data to this part line
        data = last_line

修复代码的最简单方法是打印接收到的数据而不用添加新行,即print语句(Python 2)和 print() 函数 (Python 3) 默认执行。像这样:

Python 2:

print data,

Python 3:

print(data, end='')

现在 print 不会在每个打印值的末尾添加自己的换行符,只会打印接收到的数据中出现的新行。结果是打印的每一行都没有根据每个 `socket.recv() 接收到的数据量进行拆分。例如:

from __future__ import print_function
import socket

s = socket.socket()
s.connect(('gump.gatech.edu', 756))

while True:
    data = s.recv(3).decode('utf8')
    if not data:
        break    # socket closed, all data read
    print(data, end='')

这里我使用了非常小的缓冲区大小 3,这有助于突出问题。

请注意,这仅修复了打印数据的 POV 问题。如果您想处理数据 line-by-line 那么您需要对传入数据进行自己的缓冲,并在收到新行或套接字关闭时处理该行。