python socket recv接收网络数据返回空字符串

AlexChenLei 2014-10-09 04:55:41
在与服务器建立连接后通过
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
接收来自后台的消息,
通过socket.recv(n)接收消息,有时候会接收到空字符串,但通过抓包发现服务器端发送过来的并非空字符串。
但如果在recv前面先sleep(10),再接收就没有这个问题, 很奇怪,感觉像是recv太快了... 我没有设置socket选项,应该默认是阻塞io,求解释。

************ 但如果sleep(2),还是有可能出现,只是不再最开始出现。

client端代码如下:


import socket, sys, time, struct
import pdb

serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#------------------------------------------------------
# Print the struct.pack Binary content as Hex
# 16 bytes per line
#------------------------------------------------------
def PrintBinHex(s, flag):
global dbugFlag
# dbug < 0: accurate output
# dbug >=0: range output

if(dbugFlag < 0):
if(flag != -1*dbugFlag):
return
elif(flag < dbugFlag):
return

bytes = bytearray(s)
cnt = 0
for i in bytes:
cnt=cnt+1
print "%02x" % i,

if (cnt%16) == 0:
print "\n"
elif (cnt%8) == 0:
print " ",
print


#------------------------------------------------------
# InitFrontEnd
# connect to the target
#------------------------------------------------------
def InitFrontEnd():
print "Connect to host..."
try:
port = 123456
host = "192.168.1.100"
serverSocket.connect((host, port))

except socket.error, e:
print "Connection error: %s" % e
sys.exit(1)
else:
print "Connection succ..."

#------------------------------------------------------
# RecvN
# recv N bytes to target
#------------------------------------------------------
def RecvN(socket, n):
return socket.recv(n)


#------------------------------------------------------
# Recv Fake Rsp Info from server
# get only 1 int16 first for msg len and then msg body from server to test the connection
#------------------------------------------------------
def RecvWholeMsgFromServer():
global serverSocket
#print "try to get... "
#pdb.set_trace()
lenBuf = ''
length = 0
try:

lenBuf = RecvN(serverSocket, 2)
length, = struct.unpack('!H', lenBuf)
bodyBuf = RecvN(serverSocket, length-2)
Msg = lenBuf + bodyBuf
except :
print "****** Except Length : %d *******\n" %length
PrintBinHex(lenBuf, 1)
raise


#------------------------------------------------------
# Get Msg from Server
# RecvLoop
#------------------------------------------------------
def RecvLoop():
x = 1
while x <= 100:
RecvWholeMsgFromServer()
x+=1
if x % 10 == 0:
print "Recv [%d]" % x


#------------------------------------------------------
# connect to server and get msg
#
#------------------------------------------------------
def FrontEndConnAndRecv():
# 1. client connect BackEnd
InitFrontEnd()
#time.sleep(10) <------------------------ 如果不加这里,RecvN会返回空字符串
RecvLoop()


=========================================================
执行结果如下:

Connect to host...
Connection succ...
****** Except Length : 0 *******

00 00
Traceback (most recent call last):
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 317, in <module>
FrontEndConnAndRecv()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 268, in FrontEndConnAndRecv
RecvLoop()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 252, in RecvLoop
RecvWholeMsgFromServer()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 237, in RecvWholeMsgFromServer
bodyBuf = RecvN(serverSocket, length-2)
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 105, in RecvN
return socket.recv(n)
ValueError: negative buffersize in recv

---------------------------------------------------------------------------
sleep(2)时,在中途出现读取失败:


Connect to host...
Connection succ...
Recv [10]
Recv [20]
Recv [30]
Recv [40]
Recv [50]
Recv [60]
****** Except Length : 0 *******

00 00
Traceback (most recent call last):
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 317, in <module>
FrontEndConnAndRecv()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 268, in FrontEndConnAndRecv
RecvLoop()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 252, in RecvLoop
RecvWholeMsgFromServer()
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 237, in RecvWholeMsgFromServer
bodyBuf = RecvN(serverSocket, length-2)
File "R:\Project\MyTest1\sources\tools\MyTool1\MyTest1_SendAndRecvTest
\FrontEnd.py", line 105, in RecvN
return socket.recv(n)
ValueError: negative buffersize in recv
...全文
2745 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
AlexChenLei 2014-10-10
  • 打赏
  • 举报
回复
引用 1 楼 panghuhu250 的回复:

...
        lenBuf = RecvN(serverSocket, 2)       
        length, = struct.unpack('!H', lenBuf)           
        bodyBuf = RecvN(serverSocket, length-2)
        Msg = lenBuf + bodyBuf
可能的问题: 1. recv(n)有可能接收到少于n个byte的信息, 所以recv(n)后要检查接收到的信息长度, 不够的话再调用recv接收. 1. 数据流格式你理解的对不对?数据流是否正确? (听起来有点冒犯, 但这确实是一个问题, 比如length好象表示信息的长度, 它包括length所用的两个byte吗?)
谢谢回复,问题原因就是:”recv(n)有可能接收到少于n个byte的信息“,对python不是很熟,理解错误,我之前以为python的recv(n)会在收到n个bytes才返回。现象的原因是因为我的每个package都是[msglen:2 | data:N],并且data区全0x0,由于前一次根据msglen读取data的时候,并没有完整读完所有len的data区,我就直接认为data区已经读完,紧接着读取下一个package的len时,实际上是data区的内容,这时len的内容即为data区中的全0,导致下一个data的len计算为负数。将RecvN调整为:

#------------------------------------------------------
# RecvN
#     recv N bytes to target
#------------------------------------------------------
def RecvN(socket, n):	
	totalContent = ''
	totalRecved = 0
	while totalRecved < n:
		onceContent = socket.recv(n - totalRecved)		
		totalContent += onceContent
		totalRecved = len(totalContent)

	return totalContent
angel_su 2014-10-10
  • 打赏
  • 举报
回复
空字串unpack肯定错,所以开始确实是收了2个字符,只是解析成整形0,至于什么原因就不知道了...
The_Third_Wave 2014-10-10
  • 打赏
  • 举报
回复
mark,soket玩的少
jeky_zhang2013 2014-10-09
  • 打赏
  • 举报
回复
还没有尝试分开 接收,帮顶下
panghuhu250 2014-10-09
  • 打赏
  • 举报
回复

...
        lenBuf = RecvN(serverSocket, 2)       
        length, = struct.unpack('!H', lenBuf)           
        bodyBuf = RecvN(serverSocket, length-2)
        Msg = lenBuf + bodyBuf
可能的问题: 1. recv(n)有可能接收到少于n个byte的信息, 所以recv(n)后要检查接收到的信息长度, 不够的话再调用recv接收. 1. 数据流格式你理解的对不对?数据流是否正确? (听起来有点冒犯, 但这确实是一个问题, 比如length好象表示信息的长度, 它包括length所用的两个byte吗?)

37,722

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧