socket.recv 完整接收数据

2015-11-15 13:10:12 +08:00
 wowpanda

data=b''
while True:
data+=socket.recv(4096)
if len(data)<=0:
break

我是用循环来实现的,但是会阻塞.
用 setblocking(0),然后又会好像老是出现 reset by peers 。
求 v2 菊苣们指点啊
@_@

7628 次点击
所在节点    Python
13 条回复
loqixh
2015-11-15 13:35:03 +08:00
你这几句代码有 N 个错误。。。。你最好先弄本网络编程的基础书看看
auser
2015-11-15 13:42:41 +08:00
1 楼说的对
wowpanda
2015-11-15 13:48:20 +08:00
@loqixh okay,看了个博客就直接开干了。看来还是要看书啊
wowpanda
2015-11-15 13:51:54 +08:00
@loqixh 你说的错误在哪儿?
问题是我能接受到 4096 个 byte 的数据啊
eamars
2015-11-15 14:08:49 +08:00
@wowpanda
你在接受了 4096 个数据之后直接添加到了 data 中,而 socket 并没有保证本次接受可以成功,如果产生了错误,比如网络中断,或者出现了 reset by peer ,则 socket 很有可能返回一个 None ,或者别的神奇的数据,这时候 data += None 是什么鬼?
然后你的 data 每次是 append 的,所以只要有任意一次数据传输成功, if len(data)<=0 就永远为 false

好好读书
mengzhuo
2015-11-15 14:12:35 +08:00
同意 1 楼观点,先看看书吧
给你点提示,阻塞有时候并不是坏事, setblocking 会触发 EAGAIN
你的代码 exception 没有处理,自然程序 crash , crash 之后操作系统会回收你的 socket ,对端自然会 reset 了
wowpanda
2015-11-15 14:23:25 +08:00
感谢菊苣们的指点,我去看书了 @_@
偷懒真是害人不浅啊
ryd994
2015-11-16 02:49:32 +08:00
block=recv
if block:
data+block
else: break
这样就行了
non blocking 不是你这样用的
wowpanda
2015-11-16 09:05:27 +08:00
@ryd994 不加循环,怎么知道是不是把数据都接受完整了呢? block 为空不能说明是接收完所有对端返回的数据吧了吧,如果是非阻塞,是不是要设置个超时?或者先接收一部分把 header 里面的 content length 给解析出来,再设置为 recv 的参数?
ryd994
2015-11-16 09:51:47 +08:00
@wowpanda 这当然是循环内的,不然也就没有 data+=block 了
非阻塞自然就不存在超时这个概念,系统 buffer 里有多少返回多少
recv 的参数不是给你指定接收长度用的而是防止溢出用的。如果你用 C 写过这方面的程序,就会明白这个道理。
ryd994
2015-11-16 09:54:21 +08:00
@wowpanda 如果是 blocking 的 recv ,要么出错,要么有数据
wowpanda
2015-11-16 10:11:16 +08:00
@ryd994
^_^我误解了,抱歉。
我的意思是 recv 读取的是缓冲区的数据,但是对端传送过来的数据不是一次就传完了,或者是在网络中因为数据量比较大,系统要接受好几次才能接收所有的。那么这种情况下,我要怎么写?
ryd994
2015-11-16 10:53:28 +08:00
@wowpanda 把你 while 里面改成我刚才那一段就好了
不要 nonblocking
如果 block 为空,那就说明结束了
如果非常大的话就要先写入文件了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/236313

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX