Python 处理以换行符结尾的套接字数据
当我需要varPython 处理以换行符结尾的套接字数据,python,python-2.7,python-3.x,sockets,tcp,Python,Python 2.7,Python 3.x,Sockets,Tcp,当我需要var数据以换行符结束时,处理套接字连接的最佳方法是什么? 我正在使用下面的代码,但有时tcp数据包被分块,需要很长时间才能匹配data.endswith(“\n”)。 我也尝试过其他方法,比如如果最后一行不是以\n结尾,则保存它,并将其附加到下一个循环的数据中。但这也不起作用,因为多个数据包被分块,并且第一部分和第二部分不匹配。 我无法控制另一端,它基本上发送以\r\n结尾的多行 任何建议都欢迎,因为我对套接字连接没有太多的知识 def receive_bar_updates(s):
数据
以换行符结束时,处理套接字连接的最佳方法是什么?
我正在使用下面的代码,但有时tcp
数据包被分块,需要很长时间才能匹配data.endswith(“\n”)
。
我也尝试过其他方法,比如如果最后一行不是以\n
结尾,则保存它,并将其附加到下一个循环的数据中。但这也不起作用,因为多个数据包被分块,并且第一部分和第二部分不匹配。
我无法控制另一端,它基本上发送以\r\n
结尾的多行
任何建议都欢迎,因为我对套接字连接没有太多的知识
def receive_bar_updates(s):
global all_bars
data = ''
buffer_size = 4096
while True:
data += s.recv(buffer_size)
if not data.endswith("\n"):
continue
lines = data.split("\n")
lines = filter(None, lines)
for line in lines:
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
data = ""
“正常”数据的示例:
line1\r\n
line2\r\n
line3\r\n
line1\r\n
line2\r\n
lin
分块的数据的示例:
line1\r\n
line2\r\n
line3\r\n
line1\r\n
line2\r\n
lin
基本上,您似乎想要从套接字读取行。也许您最好不要使用低级的recv
调用,而只使用sock.makefile()
并将结果视为一个常规文件,您可以从中读取以下行:从sfile中的行:…
这就留下了延迟/块问题。这可能是由发送端的错误引起的。尝试禁用该选项:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
基本上,您似乎想要从套接字读取行。也许您最好不要使用低级的recv
调用,而只使用sock.makefile()
并将结果视为一个常规文件,您可以从中读取以下行:从sfile中的行:…
这就留下了延迟/块问题。这可能是由发送端的错误引起的。尝试禁用该选项:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
我尚未测试此代码,但它应该可以工作:
def receive_bar_updates(s):
global all_bars
data = ''
buf = ''
buffer_size = 4096
while True:
if not "\r\n" in data: # skip recv if we already have another line buffered.
data += s.recv(buffer_size)
if not "\r\n" in data:
continue
i = data.rfind("\r\n")
data, buf = data[:i+2], data[i+2:]
lines = data.split("\r\n")
lines = filter(None, lines)
for line in lines:
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
data = buf
编辑:忘了提一下,我只修改了接收数据的代码,我不知道函数的其余部分(从lines=data.split(“\n”)
)是用来做什么的
编辑2:现在换行符使用“\r\n”而不是“\n”
编辑3:修复了一个问题。我还没有测试过这段代码,但它应该可以工作:
def receive_bar_updates(s):
global all_bars
data = ''
buf = ''
buffer_size = 4096
while True:
if not "\r\n" in data: # skip recv if we already have another line buffered.
data += s.recv(buffer_size)
if not "\r\n" in data:
continue
i = data.rfind("\r\n")
data, buf = data[:i+2], data[i+2:]
lines = data.split("\r\n")
lines = filter(None, lines)
for line in lines:
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
data = buf
编辑:忘了提一下,我只修改了接收数据的代码,我不知道函数的其余部分(从lines=data.split(“\n”)
)是用来做什么的
编辑2:现在换行符使用“\r\n”而不是“\n”
编辑3:修复了一个问题。您是否接受不同的连接?还是由\r\n
分割的一个数据流
当接受多个连接时,您需要等待使用s.accept()的连接,然后处理其所有数据。当您拥有所有数据包时,处理其数据,并等待下一次连接。
然后,您所做的取决于每个数据包的结构。
(例如:)
如果您使用的是一个数据流,那么您可能应该在一个单独的线程中处理您找到的每一个“行”,同时继续使用另一个线程
编辑:
所以,如果我知道你的情况是正确的;一个连接,数据是由\r\n
分割的字符串,以\n
结尾。但是,数据与您期望的不一致,而是无限循环等待\n
据我所知,套接字接口以空数据结果结束。因此,最后一个缓冲区可能以\n
结束,但随后继续获取None
对象,试图找到另一个\n
相反,请尝试添加以下内容:
if not data:
break
完整代码:
def receive_bar_updates(s):
global all_bars
data = ''
buffer_size = 4096
while True:
data += s.recv(buffer_size)
if not data:
break
if not data.endswith("\n"):
continue
lines = data.split("\n")
lines = filter(None, lines)
for line in lines:
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
data = ""
Edit2:Oops,错误代码您是否接受不同的连接?还是由\r\n
分割的一个数据流
当接受多个连接时,您需要等待使用s.accept()的连接,然后处理其所有数据。当您拥有所有数据包时,处理其数据,并等待下一次连接。
然后,您要做什么取决于每个包的结构。
(例如:)
如果您使用的是一个数据流,那么您可能应该在一个单独的线程中处理您找到的每一个“行”,同时继续使用另一个线程
编辑:
所以,如果我知道你的情况是正确的;一个连接,数据是由\r\n
分割的字符串,以\n
结尾。但是,数据与您期望的不一致,而是无限循环等待\n
据我所知,套接字接口以空数据结果结束。因此,最后一个缓冲区可能以\n
结束,但随后继续获取None
对象,试图找到另一个\n
相反,请尝试添加以下内容:
if not data:
break
完整代码:
def receive_bar_updates(s):
global all_bars
data = ''
buffer_size = 4096
while True:
data += s.recv(buffer_size)
if not data:
break
if not data.endswith("\n"):
continue
lines = data.split("\n")
lines = filter(None, lines)
for line in lines:
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
data = ""
Edit2:Oops,错误代码如果您有一个原始输入要作为行处理,io模块是您的朋友,因为它将在行中对数据包进行低级组装
您可以使用:
class SocketIO(io.RawIOBase):
def __init__(self, sock):
self.sock = sock
def read(self, sz=-1):
if (sz == -1): sz=0x7FFFFFFF
return self.sock.recv(sz)
def seekable(self):
return False
它比endswith('\n')
更健壮,因为如果一个数据包包含嵌入式换行符('ab\ncd'
),io模块将正确处理它。您的代码可能会变成:
def receive_bar_updates(s):
global all_bars
data = ''
buffer_size = 4096
fd = SocketIO(s) # fd can be used as an input file object
for line in fd:
if should_be_rejected_by_filter(line): continue # do not know what filter does...
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
如果您有一个原始输入,您希望将其作为行处理,那么io模块就是您的朋友,因为它将在行中对数据包进行低级组装
您可以使用:
class SocketIO(io.RawIOBase):
def __init__(self, sock):
self.sock = sock
def read(self, sz=-1):
if (sz == -1): sz=0x7FFFFFFF
return self.sock.recv(sz)
def seekable(self):
return False
它比endswith('\n')
更健壮,因为如果一个数据包包含嵌入式换行符('ab\ncd'
),io模块将正确处理它。您的代码可能会变成:
def receive_bar_updates(s):
global all_bars
data = ''
buffer_size = 4096
fd = SocketIO(s) # fd can be used as an input file object
for line in fd:
if should_be_rejected_by_filter(line): continue # do not know what filter does...
if line.startswith("BH") or line.startswith("BC"):
symbol = str(line.split(",")[1])
all_bars[symbol].append(line)
y = Thread(target=proccess_bars, kwargs={'symbol': symbol})
y.start()
用于将套接字包装在实现的类中。它处理缓冲、字节和字符串之间的转换,并允许您对行进行迭代。记住刷新任何写入
例如:
#/usr/bin/env蟒蛇3
导入套接字、线程、时间
def客户端(地址):
使用套接字。创建_连接(addr)作为连接:
康涅狄格州森达尔(b)