V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
wowpanda
V2EX  ›  Python

socket.recv 完整接收数据

  •  
  •   wowpanda · 2015-11-15 13:10:12 +08:00 · 7577 次点击
    这是一个创建于 3289 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    13 条回复    2015-11-16 10:53:28 +08:00
    loqixh
        1
    loqixh  
       2015-11-15 13:35:03 +08:00
    你这几句代码有 N 个错误。。。。你最好先弄本网络编程的基础书看看
    auser
        2
    auser  
       2015-11-15 13:42:41 +08:00 via Android
    1 楼说的对
    wowpanda
        3
    wowpanda  
    OP
       2015-11-15 13:48:20 +08:00
    @loqixh okay,看了个博客就直接开干了。看来还是要看书啊
    wowpanda
        4
    wowpanda  
    OP
       2015-11-15 13:51:54 +08:00
    @loqixh 你说的错误在哪儿?
    问题是我能接受到 4096 个 byte 的数据啊
    eamars
        5
    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
        6
    mengzhuo  
       2015-11-15 14:12:35 +08:00
    同意 1 楼观点,先看看书吧
    给你点提示,阻塞有时候并不是坏事, setblocking 会触发 EAGAIN
    你的代码 exception 没有处理,自然程序 crash , crash 之后操作系统会回收你的 socket ,对端自然会 reset 了
    wowpanda
        7
    wowpanda  
    OP
       2015-11-15 14:23:25 +08:00
    感谢菊苣们的指点,我去看书了 @_@
    偷懒真是害人不浅啊
    ryd994
        8
    ryd994  
       2015-11-16 02:49:32 +08:00 via Android
    block=recv
    if block:
    data+block
    else: break
    这样就行了
    non blocking 不是你这样用的
    wowpanda
        9
    wowpanda  
    OP
       2015-11-16 09:05:27 +08:00 via Android
    @ryd994 不加循环,怎么知道是不是把数据都接受完整了呢? block 为空不能说明是接收完所有对端返回的数据吧了吧,如果是非阻塞,是不是要设置个超时?或者先接收一部分把 header 里面的 content length 给解析出来,再设置为 recv 的参数?
    ryd994
        10
    ryd994  
       2015-11-16 09:51:47 +08:00 via Android
    @wowpanda 这当然是循环内的,不然也就没有 data+=block 了
    非阻塞自然就不存在超时这个概念,系统 buffer 里有多少返回多少
    recv 的参数不是给你指定接收长度用的而是防止溢出用的。如果你用 C 写过这方面的程序,就会明白这个道理。
    ryd994
        11
    ryd994  
       2015-11-16 09:54:21 +08:00 via Android
    @wowpanda 如果是 blocking 的 recv ,要么出错,要么有数据
    wowpanda
        12
    wowpanda  
    OP
       2015-11-16 10:11:16 +08:00 via Android
    @ryd994
    ^_^我误解了,抱歉。
    我的意思是 recv 读取的是缓冲区的数据,但是对端传送过来的数据不是一次就传完了,或者是在网络中因为数据量比较大,系统要接受好几次才能接收所有的。那么这种情况下,我要怎么写?
    ryd994
        13
    ryd994  
       2015-11-16 10:53:28 +08:00 via Android
    @wowpanda 把你 while 里面改成我刚才那一段就好了
    不要 nonblocking
    如果 block 为空,那就说明结束了
    如果非常大的话就要先写入文件了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2013 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 78ms · UTC 00:48 · PVG 08:48 · LAX 16:48 · JFK 19:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.