Python套接字正在从服务器接收不一致的消息
因此,我对网络非常陌生,我使用Python库连接到一个正在传输位置数据流的服务器 下面是使用的代码Python套接字正在从服务器接收不一致的消息,python,sockets,networking,tcp,client,Python,Sockets,Networking,Tcp,Client,因此,我对网络非常陌生,我使用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')
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建立到服务器的原始连接时,我只得到了正确的形式,而没有得到拆分。所以我想一定有什么事情在分裂信息。或者是腻子在做什么来确保正确组装
我需要的是变量data
始终包含正确的行。你知道如何做到这一点吗?编辑:
socket.recv()
正在阻塞,就像其他人所说的那样,每次调用该方法时都不会得到准确的一行。因此,套接字正在等待数据,得到它能得到的,然后返回。打印时,由于pythons默认的end参数,您可能会得到比预期更多的换行符。因此,要从服务器获取原始数据,请使用以下命令:
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()
最好将套接字视为一个连续的数据流,它可能以点滴或洪水的形式到达 特别是,接收者的任务是将数据分解为它应该包含的“记录”,套接字不知道如何神奇地为您执行此操作。这里的记录是行,因此您必须读取数据并自己拆分成行 您不能保证一个
recv
将是一个完整的行。它可以是:
- 只是一条线的一部分李>
- 或几行李>
- 或者,很可能是几行和另一部分行
修复代码的最简单方法是打印接收到的数据而不添加新行,默认情况下,
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问题。如果要逐行处理数据,则需要对传入的数据进行自己的缓冲,并在收到新行或套接字关闭时处理该行。tcp和套接字会发生这种情况。理论上,它可以一次到达一个字节。你的代码需要重新缝合。至于实现这一点的方法,您可以将头合并到数据包中。如果将前2或4个字节设为数据的长度,则重新组合应该很简单。请参阅此处的答案,以了解发生这种情况的更详细说明:与此答案相反,
socket.recv
是阻塞的,除非套接字已显式设置为非阻塞,或已关闭,或存在信号中断。此外,此答案不涉及收到的部分行。错误。a) 默认情况下,socket.recv
处于阻塞状态,b)socket.recv
在连接关闭时返回空字符串。c) 空字符串是空的。@donkopotamus Right。它被阻塞了,我将删除它。但是,如果它是非阻塞的,我的回答确实解释了为什么会有部分行。@mhawke我说的是,如果你用print函数打印一个空字符串,你得到的是一个换行符,而不是你想要的“nothing”expected@TisteAndii:你已经纠正了我的反对意见,但是你添加了一个无限循环作为一个新问题。这是不必要的复杂。只需在原始程序中将end参数设置为空字符串,就可以了。再看看endswith的论点;您缺少了一个字符…这完全取决于您可能希望如何处理此数据。。。如果你不只是打印它,而是想把它存储起来进行分析,或者通过正则表达式提取信息,那么你就需要整理完整的行。对……我想问题的最后一行会让事情变得混乱……但是从他以前的陈述和代码来看,我想他只想打印回答。即使他想保存行,使用一个列表也会更有效率,因为append()的成本是分摊的,收集块并最终在列表上调用join()。字符串连接,特别是当你可以得到一个大的响应时,效率会非常低。这是我所需要的最好的解决方案!这是因为我需要将其插入数据库,这是最好的解决方案。这非常适合打印,但我确实需要将其耦合。我现在在想,我将只记录它,并从这一点上完成它。然后处理日志文件。
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='')