python socket 一个很简单的问题把我难住了 - V2EX
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
eightqueen
V2EX    Python

python socket 一个很简单的问题把我难住了

  •  
  •   eightqueen 2016-04-10 17:14:04 +08:00 12231 次点击
    这是一个创建于 3501 天前的主题,其中的信息可能已经有所发展或是发生改变。
    import socket respOnse= 'HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-Length: 11\r\n\r\nHello World' server = socket.socket() server.bind(('0.0.0.0', 9527)) server.listen(1024) while True: client, clientaddr = server.accept() # blocking request = client.recv(1024) # blocking print request client.send(response) # maybe blocking client.close() 

    这个例子很简单,运行起来也没啥问题,但是我不明白 recv 这个函数是怎么判断客户端的数据都传过来了?比如客户端应该传 10B 的数据,先传了 5B ,然后隔了 1 秒,此时 recv 应该返回收到的 5B 数据,还是继续等,那要等到什么时候呢?

    16 条回复    2016-06-16 10:36:19 +08:00
    des
        1
    des  
       2016-04-10 17:29:34 +08:00 via Android
    client.recv(len)
    在接收到至少 len 字节的数据之前,造成一个阻塞,并暂停脚本运行( block )。但是, 如果接收到中断信号,或远程服务器断开连接,该函数将返回少于 len 字节的数据。
    magicdawn
        2
    magicdawn  
       2016-04-10 17:30:08 +08:00
    timeout
    Mutoo
        3
    Mutoo  
       2016-04-10 17:37:04 +08:00
    tcp 协议有一个 push 标记,会让传输层立即把数据传给应用层,即使缓冲区未满。
    anexplore
        4
    anexplore  
       2016-04-10 18:08:42 +08:00 via iPhone
    可以看一下这个 http://m.blog.csdn.net/article/details?id=7689409 ,在应用层则可以通过设置数据长度或者关闭 socket 等方法表示数据接收完毕
    micyng
        5
    micyng  
       2016-04-10 18:33:53 +08:00 via Android
    如果是阻塞模式,就一直读
    gamexg
        6
    gamexg  
       2016-04-10 19:43:06 +08:00
    不会等待,而是直接返回 5B 数据。
    recv 意思是接受不超过 len 长度的数据。一般在阻塞模式下必须收到数据才返回,但是不在意到底收到了多少数据,也就是返回的数据可以不够 len 长度。
    在阻塞模式下除非远端关闭连接(包括关闭单个方向的连接)否则必定读到数据才返回。也就是如果 recv 返回的数据是空,那么表示连接断开了。

    对了上面没考虑超时的问题。
    mhycy
        7
    mhycy  
       2016-04-10 19:46:37 +08:00   1
    如果需要长度可保证的传输请用 UDP ,那是包协议(而 TCP 是流协议)
    如果需要在 TCP 做包处理,请在此基础上实现长度判断以及异常处理
    (例如发生拔网线之类不会产生任何提示的网络中断)
    gamexg
        8
    gamexg  
       2016-04-10 19:47:44 +08:00
    对了,还要注意 client.send ,这个函数返回已发送的字节数, python 不保证所有数据都发出去了。你需要自己检查是否都发出去了,如果没有那么需要继续通过 client.send 发送剩余的内容。可以换成 sendall 来解决。
    bp0
        9
    bp0  
       2016-04-10 20:34:09 +08:00
    通常都是在 TCP 之上增加应用层协议,先发送长度或者类似信息,然后再发送数据的。

    就像 @mhycy 说的, TCP 是流协议不能保证你这边发送 5B 时对方会马上收到。有可能你连续发送 2 次 5B ,对方一次收到 10B 。
    ayiis
        10
    ayiis  
       2016-04-10 20:57:32 +08:00
    如果楼主其实是想问 http 的话:
    1. 读取 http 的 header
    2. 解析 header
    3.1 如果 Transfer-Encoding:chunked ,则需要按段读取,并把每段的段头和段尾删除
    3.2 否则获取 Content-Length ,读到指定长度完毕(如果后面还有数据则截断
    4. 配合超时

    如果是 tcp 的话,我觉得 tcp 只有对方发送 FIN 或者 RST 之后才算结束,所以如果对方 SYN flood 你
    ryanking8215
        11
    ryanking8215  
       2016-04-11 08:55:34 +08:00
    TCP 是流方式,有粘包和漏包的问题,所以一般协议里都需要同步头和数据长度等信息,让应用层来确定消息边界。
    eightqueen
        12
    eightqueen  
    OP
       2016-04-11 10:36:46 +08:00
    @Mutoo 没错,就是 push ,谢谢
    mengzhuo
        13
    mengzhuo  
       2016-04-13 08:14:38 +08:00
    一般是 5B

    @bp0 这个得看链路上有没有合包的设备,但是很少见,自己 wireshark 抓一下就知道了
    bp0
        14
    bp0  
       2016-04-13 10:29:35 +08:00
    @mengzhuo 像楼主这种局域网的情况下,中间延迟 1s ,肯定是先收到一个 5b ,然后再收到另外一个 5b 。

    但是,如果中间没有延迟 1s ,客户端连续调用两次发送 5b ,在客户端的 TCP 层就会被 Nagle 算法合并了,根本不需要合包的设备。

    还有,如果是互联网,那么即使延迟 1s ,最终到达服务器的数据包也有可能已经被合并成 10b 的一包了。
    ayiis
        15
    ayiis  
       2016-04-16 23:46:40 +08:00
    aec4d
        16
    aec4d  
       2016-06-16 10:36:19 +08:00
    @des 你的理解是错的 当有数据可以读取的时候进行读取 最多读取 len 字节 并不是你想的一定会读到 len 字节然后才执行下一步
    你可以下载一个比较大的文件验证一下
    关于     帮助文档     自助推广系统     博客     API     < href="/faq" class="dark" target="_self">FAQ     Solana     5904 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:04 PVG 10:04 LAX 18:04 JFK 21:04
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86