为什么在Python中从套接字接收字符串直到\n换行符?
我本来是想通过一个TCP连接接收两行字符串,但实际上我只收到了第一行,直到换行符为止。
socket = socket(AF_INET,SOCK_STREAM)
socket.connect((ip,port))
data = socket.recv(1024)
print "%s" % data
如果我现在调用接收函数,它会接收到换行后的第二部分字符串。但这并不是我想要的。其实它应该在第一次调用时就返回整个字符串。当我用nc命令连接到服务器时,刚开始连接时我能正常收到字符串。为什么会这样呢?
1 个回答
11
因为TCP是一种流式协议(通过SOCK_STREAM
可以看出来),所以它没有固定的消息边界或数据包。你不能仅仅通过一次调用recv
就确定你收到了所有的数据。你需要在一个循环中不断调用recv
,把接收到的数据添加到一个缓冲区中,直到你觉得数据够了为止。大多数只处理文本的协议会使用换行符来表示读取结束,并对接收到的数据进行处理。其他协议可能会使用其他字符或字节序列。
在你的情况下,如果没有特殊字符来表示当前数据的结束,你有两个解决方案:
使用超时:如果一段时间内没有收到新数据,就打印已经接收到的数据。
非阻塞套接字:简单地在循环中读取数据,把数据添加到内部缓冲区。当调用
recv
时出现错误,且errno
等于errno.EWOULDBLOCK
,这时就表示暂时没有更多数据可以读取,可以打印已接收到的数据。
第二种方案,加上select
这个包,可能是最好的选择。
编辑
这里有一个简单的例子来说明我的意思。这个例子可能不能直接工作,需要一些调整,但希望它能给你提供一些基础。
# Need to import: package socket, package select, package errno
# Create socket and connect to server
# Make the socket non-blocking (see http://docs.python.org/library/socket.html#socket.socket.setblocking)
socket.setblocking(0)
run_main_loop = True
while run_main_loop:
# Wait for events...
read_ready, _, _ = select.select([socket], None, None)
if socket in read_ready:
# The socket have data ready to be received
buffer = ''
continue_recv = True
while continue_recv:
try:
# Try to receive som data
buffer += socket.recv(1024)
except socket.error, e:
if e.errno != errno.EWOULDBLOCK:
# Error! Print it and tell main loop to stop
print 'Error: %r' % e
run_main_loop = False
# If e.errno is errno.EWOULDBLOCK, then no more data
continue_recv = False
# We now have all data we can in "buffer"
print '%r' % buffer
socket.close()