什么时候以及为什么socket.send()在python中返回0?

Ste*_*o M 13 python sockets python-3.x

python3 套接字编程如何呈现此代码片段

class MySocket:
    """demonstration class only
      - coded for clarity, not efficiency
    """

    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(
                            socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock

    def connect(self, host, port):
        self.sock.connect((host, port))

    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent

    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return b''.join(chunks)
Run Code Online (Sandbox Code Playgroud)

如果套接字send方法返回0 ,则发送循环中断.

这个片段背后的逻辑是,当send方法返回'0 bytes sent'时,套接字连接的发送方应该放弃发送数据的努力.这对于该recv方法肯定是正确的,其中在阻塞模式下为套接字读取的零字节应该被解释为EOF,因此读取方应该放弃.

但是我无法理解在哪种情况下该send方法可以返回零.我对python套接字的理解是send由于OS级别的缓冲而立即返回.如果缓冲区已满send将阻塞,或者如果远程端连接已关闭,则会引发异常.

最后假设send返回零而不引发异常:这是否真的表明所有未来的send调用都将返回零?

我做了一些测试(尽管::1在OS X上只连接了套接字)并且无法找到send返回0的情况.

编辑

HOWTO指出:

但是,如果您计划重新使用套接字进行进一步传输,则需要意识到套接字上没有EOT.我再说一遍:如果在处理0字节后套接字send或recv返回,则连接已断开.如果连接没有被破坏,你可以永远等待一个recv,因为套接字不会告诉你没有什么可读的(现在).

很容易找到recv返回0 的情况:当远程(发送)端调用时socket.shutdown(SHUT_WR),recv接收端的进一步返回0并且不会引发任何异常.

我正在寻找一个具体的例子,你可以证明接收0零send表示连接断开(在发送时将继续返回0).

mem*_*tum 5

看到问题后,我被震惊了,因为sendC调用可以返回0个字节并且连接当然仍然存在(套接字不能简单地在给定时刻发送更多字节)

我决定"使用源代码",除非我非常错(这可能一直是经常发生),这是HOWTO中的一个错误.

链:

  • send 是别名 sock_send
  • sock_send 轮流打电话 sock_call
  • sock_call 轮流打电话 sock_call_ex
  • sock_call轮流调用sock_send_impl(从传递链接开始sock_send)

平仓:

  • sock_send_impl返回truefalse(1或0)return (ctx->result >= 0)

  • sock_call_ex 回报

    • -1如果sock_send_impl回来false
    • 0如果sock_send_impl回来true
  • sock_call 透明地返回此值.

  • sock_send

    • 返回NULLa -1(因为已经设置了错误并且将引发异常)

    • 回报ctx->result0sock_call

      而且ctx->result是由C调用写入的字节数sendsock_send_impl.

该链显示如果0已发送字节,则没有错误,这实际上是潜在的真实插座情况.

如果我的逻辑错了,请有人告诉我.