当前位置: 首页 > 知识库问答 >
问题:

如果在超时发生之前没有接收到数据,Python的socket.recv()会为非阻塞套接字返回什么?

邹浩
2023-03-14

好吧,好吧,但是当我的插座不阻塞时会发生什么??我搜索了一点(可能不够,谁知道呢?)并且不知道如何判断对方何时使用非阻塞套接字关闭了连接。似乎没有任何方法或属性告诉我们这一点,并且将recv()的返回值与空字符串进行比较似乎绝对没有用……只是我有这个问题吗?

作为一个简单的示例,假设我的套接字的超时设置为1.2342342秒(无论您在这里喜欢什么非负数),并且我调用socket.recv(1024),但是另一方在1.2342342秒期间没有发送任何内容。recv()调用将返回一个空字符串,我不知道连接是否还在运行...

共有1个答案

陶英达
2023-03-14

在无数据可用的非阻塞套接字的情况下,recv将抛出socket.error异常,异常值的errno为EAGAIN或eWouldBlock。示例

import sys
import socket
import fcntl, os
import errno
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
fcntl.fcntl(s, fcntl.F_SETFL, os.O_NONBLOCK)

while True:
    try:
        msg = s.recv(4096)
    except socket.error, e:
        err = e.args[0]
        if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
            sleep(1)
            print 'No data available'
            continue
        else:
            # a "real" error occurred
            print e
            sys.exit(1)
    else:
        # got a message, do something :)

在使用socket.setTimeout(n)socket.setBlocking(False)通过超时启用非阻塞行为的情况下,情况略有不同。在这种情况下,仍然会引发socket.error,但是在超时的情况下,异常的附带值始终是设置为“timed out”的字符串。因此,要处理这个案件,您可以:

import sys
import socket
from time import sleep

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
s.settimeout(2)

while True:
    try:
        msg = s.recv(4096)
    except socket.timeout, e:
        err = e.args[0]
        # this next if/else is a bit redundant, but illustrates how the
        # timeout exception is setup
        if err == 'timed out':
            sleep(1)
            print 'recv timed out, retry later'
            continue
        else:
            print e
            sys.exit(1)
    except socket.error, e:
        # Something else happened, handle error, exit, etc.
        print e
        sys.exit(1)
    else:
        if len(msg) == 0:
            print 'orderly shutdown on server end'
            sys.exit(0)
        else:
            # got a message do something :)

正如注释中所指出的,这也是一个更可移植的解决方案,因为它不依赖于操作系统特定的功能来将套接字置于非阻塞模式。

 类似资料:
  • 我正在开发一个使用TCP套接字的客户端(Java)/服务器(C++)应用程序。我使用的协议由2个字节开头的消息组成,这些字节定义了消息内容的类型。所以基本上,接收线程在循环中等待接收数据。但我希望使用套接字的超时通知其他主机发送数据的时间过长。

  • 问题内容: 为什么有人会喜欢阻止写而不是非阻止写?我的理解是,仅当您想确保写方法返回后,另一端获得了TCP数据包时,才希望阻止写操作,但是我什至不知道这是可能的。您将必须刷新,而刷新则必须刷新 底层操作系统的写套接字缓冲区 。那么,无阻塞套接字写是否有任何缺点?就性能而言,拥有较大的底层写套接字是否会缓冲一个不好的主意?我的理解是,底层套接字写缓冲区越小,当底层套接字缓冲区已满且isWritabl

  • 问题内容: 我想创建一个非阻塞连接。像这样: 为此,我使用了另一个线程,无限循环和Linux epoll。像这样(伪代码): 如果我先运行服务器,然后运行客户端,那么一切正常。如果我先运行客户端,请稍等一会儿,再运行服务器,然后客户端将无法连接。 我究竟做错了什么?也许可以做不同的事情? 问题答案: 您应该使用以下步骤进行异步连接: 用创建套接字 开始与 如果返回值既不是也不是,则中止并返回错误

  • 我正在使用TCP/IP套接字,我已经读过函数。因此,每当对等体断开连接时,recv按照文档返回0,但在windows上它不返回零,而是返回-1,并且中的值是我无法理解它为什么这样做。同样的代码在Linux中运行得非常好。

  • 下面的代码允许服务器等待客户端连接到(已经绑定的)套接字。它在客户端连接到套接字时终止,或者在“server_run”取值0时终止:这允许代码的其他部分在合适的时候关闭服务器。 根据对另一个帖子(C:non blocking sockets with timeout:how to check if connection request was made?)的回答和评论,这不是一种方法,因为它涉及到

  • 问题内容: 当我直接使用(没有诸如Scanner之类的界面)接收数据时,它不会阻塞。但是,当我尝试使用Scanner时(类似于我们从接收字符串的方式),它确实可以。我想知道这样做的原因,以及所连接的Socket提供给您的InputStream与in的不同之处。 用于测试的客户端(用于两个服务器) 挂起的代码: 不阻塞的代码: 问题答案: (我认为您已经知道了这一点,但是…) 该方法返回当前行的其余