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

为什么 Python 在 Windows 系统下 socket(blocking) recv 会得到长度为 0 的空数据

  •  
  •   just1 · 2021-10-12 02:08:37 +08:00 · 2805 次点击
    这是一个创建于 1174 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网上查找都是说 recv 为空代表对等方已经关闭了连接,但事实上并没有关闭?我依然可以接收到新的数据,也可以发送。

    https://stackoverflow.com/questions/3091010/recv-socket-function-returning-data-with-length-as-0

    并且同样的代码在 linux 下就很正常,这个情况只在 Windows 下复现。并且非常神奇,socket 刚创建没问题,10 分钟后(一秒不差)就出现 recv 空数据

    我的 Python 版本为 3.8

    第 1 条附言  ·  2021-10-12 11:06:08 +08:00
    出现这个问题之后,双方都能够正常收发。不过目前这个服务端不是我这边的,所以我就先只贴一下客户端代码
    class Recv(threading.Thread):
    def __init__(self, s, stop_event=None):
    super(Recv, self).__init__()
    self.setDaemon(True)
    self.q = queue.Queue()
    self.s = s # socket
    self.stop_event = stop_event if stop_event else threading.Event()

    def run(self):
    while not self.stop_event.is_set():
    try:
    data = self.s.recv(131072)
    if len(data) != 0:
    self.q.put(data)
    except (ConnectionResetError, OSError, ConnectionAbortedError) as e:
    logging.error('recv', str(e))
    第 2 条附言  ·  2021-10-12 11:06:46 +08:00

    格式乱了。。。 出现这个问题之后,双方都能够正常收发。不过目前这个服务端不是我这边的,所以我就先只贴一下客户端代码

    class Recv(threading.Thread):
    
        def __init__(self, s, stop_event=None):
            super(Recv, self).__init__()
            self.setDaemon(True)
            self.q = queue.Queue()
            self.s = s  # socket
            self.stop_event = stop_event if stop_event else threading.Event()
    
        def run(self):
            while not self.stop_event.is_set():
                try:
                    data = self.s.recv(131072)
                    if len(data) != 0:
                        self.q.put(data)
                except (ConnectionResetError, OSError, ConnectionAbortedError) as e:
                    logging.error('recv', str(e))
    
    11 条回复    2021-10-13 01:05:25 +08:00
    dingwen07
        1
    dingwen07  
       2021-10-12 02:53:46 +08:00 via iPhone
    我没有遇到过
    不过我没试过 10 分钟的,之后试一下
    jedihy
        2
    jedihy  
       2021-10-12 03:29:59 +08:00
    单步进去看看这个 0 是不是 winsock 的 recv()返回的。如果是,并且你还能收到新数据,那可能是 OS 的 bug 。不然可能是 python 的 bug 。
    lzp729
        3
    lzp729  
       2021-10-12 05:52:01 +08:00 via iPhone
    超时了
    skinny
        4
    skinny  
       2021-10-12 09:13:20 +08:00
    问得没头没尾的,你代码怎么写的?
    est
        5
    est  
       2021-10-12 09:40:59 +08:00
    > 我依然可以接收到新的数据,也可以发送。

    不代表连接没关闭。。。。

    你发送,对方可以不收。。并且对方再通知你,不要联系了。
    makelove
        6
    makelove  
       2021-10-12 10:48:00 +08:00
    这种不应该贴一下最小复现代码吗
    dreamtrail
        7
    dreamtrail  
       2021-10-12 11:40:44 +08:00
    也许是系统或者 python 有 bug,但这种可能性挺小的
    muzuiget
        8
    muzuiget  
       2021-10-12 12:36:14 +08:00
    只是缓冲区没有数据而已,返回负数才是错误啊,比如连接关闭,再 recv 多几次就应该出现负数了。
    muzuiget
        9
    muzuiget  
       2021-10-12 12:37:35 +08:00
    晕,原来是 Python,但是你贴的爆栈帖子说的是 C,两者语义未必一直,还是看 Python 文档好了。
    just1
        10
    just1  
    OP
       2021-10-12 15:05:53 +08:00 via Android
    @muzuiget 按照理解,blocking 下应该不会返回空数据才是
    Shatyuka
        11
    Shatyuka  
       2021-10-13 01:05:25 +08:00 via Android
    长连接 keepalive
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2612 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:15 · PVG 23:15 · LAX 07:15 · JFK 10:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.