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
V2EX  ›  Python

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

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


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

    我试着还原你的问题。client 发送 32k 数据,server 收取 24k 数据,并没有任何异常发生。
    skinny
        18
    skinny  
    OP
       2019-09-01 20:34:39 +08:00
    @BingoXuan 你没有理解我的意思。
    sujin190
        19
    sujin190  
       2019-09-02 17:33:11 +08:00
    @BingoXuan #17 他的意思的是单个 UDP 包,UDP 没有重排,所以应该是一次必须把整个 UDP 包都接收了,不能分成两次读取一个 UDP 包,跨 UDP 包当然不会有问题了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1531 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:10 · PVG 01:10 · LAX 10:10 · JFK 13:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.