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 · 56 天前 · 1938 次点击
    这是一个创建于 56 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    我的 Python 版本为 3.8

    第 1 条附言  ·  56 天前
    出现这个问题之后,双方都能够正常收发。不过目前这个服务端不是我这边的,所以我就先只贴一下客户端代码
    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 条附言  ·  56 天前

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

    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  
       56 天前 via iPhone
    我没有遇到过
    不过我没试过 10 分钟的,之后试一下
    jedihy
        2
    jedihy  
       56 天前
    单步进去看看这个 0 是不是 winsock 的 recv()返回的。如果是,并且你还能收到新数据,那可能是 OS 的 bug 。不然可能是 python 的 bug 。
    lzp729
        3
    lzp729  
       56 天前 via iPhone
    超时了
    skinny
        4
    skinny  
       56 天前
    问得没头没尾的,你代码怎么写的?
    est
        5
    est  
       56 天前
    > 我依然可以接收到新的数据,也可以发送。

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

    你发送,对方可以不收。。并且对方再通知你,不要联系了。
    makelove
        6
    makelove  
       56 天前
    这种不应该贴一下最小复现代码吗
    dreamtrail
        7
    dreamtrail  
       56 天前
    也许是系统或者 python 有 bug,但这种可能性挺小的
    muzuiget
        8
    muzuiget  
       56 天前
    只是缓冲区没有数据而已,返回负数才是错误啊,比如连接关闭,再 recv 多几次就应该出现负数了。
    muzuiget
        9
    muzuiget  
       56 天前
    晕,原来是 Python,但是你贴的爆栈帖子说的是 C,两者语义未必一直,还是看 Python 文档好了。
    just1
        10
    just1  
    OP
       56 天前 via Android
    @muzuiget 按照理解,blocking 下应该不会返回空数据才是
    Shatyuka
        11
    Shatyuka  
       55 天前 via Android
    长连接 keepalive
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3889 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 08:21 · PVG 16:21 · LAX 00:21 · JFK 03:21
    ♥ Do have faith in what you're doing.