UDP 网络编程时,在 recvfrom 出现缓冲区过小错误时,有没有办法获得发送这个大数据报的客户端的源地址(IP, PORT)? - 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
skinny

UDP 网络编程时,在 recvfrom 出现缓冲区过小错误时,有没有办法获得发送这个大数据报的客户端的源地址(IP, PORT)?

  •  
  •   skinny 2019 年 8 月 31 日 3089 次点击
    这是一个创建于 2428 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在原始的 IP 和 UDP 数据包里有这个地址信息,可是 Python socket API 遇到缓冲区过小是直接抛异常,但是异常信息里却不提供这个源地址信息,还有,C SOCKET API 是提供这个信息的。
    19 条回复    2019-09-02 17:33:11 +08:00
    Cyshall
        1
    Cyshall  
       2019 年 8 月 31 日 via iPhone
    recvfrom()这个 syscall 最后两个参数就是发送方的地址信息阿。
    skinny
        2
    skinny  
    OP
       2019 年 8 月 31 日
    @Cyshall 那个是成功的时候才有啊。比如 server_sock.recvfrom(64),client 发送的数据报大小小于或等于 64,一切正常,返回(data, address),可如果对方发送了 65 个字节,server_sock.recvfrom(64)就会抛 OSError,也就获取不到了,OSError 实例里也没有这个信息。
    skinny
        3
    skinny  
    OP
       2019 年 8 月 31 日
    如果非要 hack 底层或写一大坨 ctypes 代码才能获取,那我就放弃算了……
    skinny
        4
    skinny  
    OP
       2019 年 8 月 31 日
    看了下 CPython socket 模块的 C 代码,没希望了……要么换语言,要么改一坨代码。
    lcdtyph
        5
    lcdtyph  
       2019 年 8 月 31 日 via iPhone
    试一下 MSG_TRUNC 这个 flag ?
    fengtons
        6
    fengtons  
       2019 年 8 月 31 日 via Android
    试一下 recvmsg 看行不行
    elfive
        7
    elfive  
       2019 年 8 月 31 日 via iPhone
    一般 UDP 包大小以不超过 MTU 为最佳,所以我一般缓冲区会根据网络类型设定不同的缓冲区大小
    BingoXuan
        8
    BingoXuan  
       2019 年 8 月 31 日 via Android
    udp 是一个一个的消息,一般都会 recv 大小是 mtu 值。如果是 tcp 流,你可以源源不断地 recv。
    skinny
        9
    skinny  
    OP
       2019 年 8 月 31 日
    @elfive
    @BingoXuan
    正常情况下来说是这样,可是你如果写一个 UDP Server,也许有恶意的或者有 BUG 的程序,发来一堆这种大于预先协商好大小的缓冲区的数据报,而你却因为这种问题导致无法记录有效数据……还是不用 Python 写 UDP Server 了。


    @lcdtyph
    @fengtons
    这两个都是 Unix/Linux 才有的,而且不符合需求。
    aguesuka
        10
    aguesuka  
       2019 年 9 月 1 日 via Android
    用 noi,超过 buff 的数据会被丢弃
    aguesuka
        11
    aguesuka  
       2019 年 9 月 1 日 via Android
    没看到是 python
    elfive
        12
    elfive  
       2019 年 9 月 1 日 via iPhone
    @skinny #9 Python 抛异常其实也算能理解,毕竟 udp socket 在调用 recvfrom()以后会清空内核中对应 udp 端口的接收缓冲区,Python 可能认为收到不完整的内容就是一种异常,所以需要你特别注意,你就封装一下,用 try...catch 捕获处理这个异常就好了。这一点,所有 udp socket 其实都一样。只是有些库或语言帮你处理了,有些则没有而已。
    skinny
        13
    skinny  
    OP
       2019 年 9 月 1 日
    @elfive 严肃的说,对于 UDP Server,最好还是是使用一个 64K 的大接收缓冲区,反正无论对面怎么样都发不了大于这个的数据报,接收后交给 Handler 检查处理以及记录,所以主楼的问题就是我有点钻牛角尖了,只是不爽 Python 就只是抛异常,却不告诉我异常是哪个源地址造成的。
    elfive
        14
    elfive  
       2019 年 9 月 1 日 via iPhone
    @skinny #13 直接分配 64K,确实是最稳妥暴力的解决方法。但如果真的有这种大小的数据过来,正常的用户通讯肯定会受到不小影响。有点类似 DDOS 的感觉了
    skinny
        15
    skinny  
    OP
       2019 年 9 月 1 日
    @elfive 正儿八经的 UDP Server 应用肯定不能拿 Python 这样写了,我是写一个 Python 网络服务测试工具时需要一个加密代理(你懂的……),却没有找到合适趁手简单好用的库,所以临时自己写一个简单一点的。
    dazhangpan
        16
    dazhangpan  
       2019 年 9 月 1 日
    目测用 kprobe + ftrace 可行
    在内核收取的方法里看
    BingoXuan
        17
    BingoXuan  
       2019 年 9 月 1 日
    @skinny
    我觉得你这种就有点炜疾忌医的感觉。不合理数据导致异常完全可以丢弃,但没必要说什么语言不合适。很多时候这些问题遇到概率实在太小了。只要在异常处理时候,处理一下就好了

    我试着还原你的问题。client 发送 32k 数据,server 收取 24k 数据,并没有任何异常发生。
    skinny
        18
    skinny  
    OP
       2019 年 9 月 1 日
    @BingoXuan 你没有理解我的意思。
    sujin190
        19
    sujin190  
       2019 年 9 月 2 日
    @BingoXuan #17 他的意思的是单个 UDP 包,UDP 没有重排,所以应该是一次必须把整个 UDP 包都接收了,不能分成两次读取一个 UDP 包,跨 UDP 包当然不会有问题了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1002 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 85ms UTC 22:59 PVG 06:59 LAX 15:59 JFK 18:59
    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