Python Socket从服务器接收不一致的消息

时间:2016-01-21 22:48:29

标签: python sockets networking tcp client

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

以下是使用的代码。

SELECT GROUP_CONCAT(tc.`name` ORDER BY tc.entity_id) AS cat_ids
FROM products AS tp
JOIN categories AS tc
ON FIND_IN_SET(tc.entity_id, tp.category_ids) 
GROUP BY tp.category_ids;

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

大部分时间它都以正确的形式到达:

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

有趣的是,当我使用Putty建立与服务器的原始连接时,我只能得到正确的表单,而不是拆分。所以我想,必然会发生一些分裂信息的事情。或Putty正在做的事情总是正确地组装它。

我需要的是变量2016-01-21 22:40:07,404,-84.396004,33.778085,0,0 始终包含正确的行。知道怎么做到这一点吗?

3 个答案:

答案 0 :(得分:1)

最好将套接字视为连续的数据流,这些数据可能会出现在点滴或单调或洪水中。

特别是,接收器的工作是将数据分解为它应该包含的“记录”,套接字并不会神奇地知道如何为您执行此操作。这里的记录是行,因此您必须自己读取数据并分成行。

您不能保证单个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

答案 1 :(得分:1)

修复代码的最简单方法是打印收到的数据,而不用添加新行,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问题。如果您想逐行处理数据,那么您需要自己缓冲传入的数据,并在收到新行或关闭套接字时处理该行。

答案 2 :(得分:-2)

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

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()