When and why socket.send() returns 0 in python?

前端 未结 2 1835
逝去的感伤
逝去的感伤 2021-02-13 14:34

The python3 socket programming howto presents this code snippet

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


        
相关标签:
2条回答
  • 2021-02-13 15:05

    I might be wrong, but I think you are looking for an impossible situation...

    As @mementum has shown in his answer, it is theoretically possible for a socket to return zero when there is no error, but also no data sent.

    However, as shown elsewhere on SO this can only happen in very specific scenarios. In my experience (and also covered in the comments to the accepted answer) you would only ever get a zero result on a non-blocking socket when the network is congested. Now Python sockets are blocking by default, which means that the kernel should wait until there is room to take some more data then return how many bytes were queued. By definition, this can never be zero.

    So, putting it all together, since your snippet doesn't reset the socket type - e.g. using the set_blocking function - it is using blocking sockets and so cannot return zero and thus cannot hit the path mementum identified.

    This is backed up by the fact that you have been unable to trigger the specific line of code no matter what you do.

    0 讨论(0)
  • 2021-02-13 15:06

    Upon seeing the question I was somehow stunned, because a send C call can return 0 bytes and the connection is of course still alive (the socket cannot simply send more bytes at that given moment in time)

    • https://github.com/python/cpython/blob/master/Modules/socketmodule.c

    I decided to "use the source" and unless I am very wrong (which can always be and often is) this is a bug in the HOWTO.

    Chain:

    • send is an alias for sock_send
    • sock_send calls in turn sock_call
    • sock_call calls in turn sock_call_ex
    • sock_call calls in turn sock_send_impl (which has been passed down the chain starting with sock_send)

    Unwinding:

    • sock_send_impl returns true or false (1 or 0) with return (ctx->result >= 0)

    • sock_call_ex returns

      • -1 if sock_send_impl returns false
      • 0 if sock_send_impl returns true
    • sock_call returns this value transparently.

    • sock_send

      • returns NULL for a -1 (because an error has been set and an exception will be raised)

      • returns ctx->result for 0from sock_call

        And ctx->result is the number of bytes written by the C call send in sock_send_impl.

    The chain shows that if 0 bytes have been sent, there is no error and this actually is a potential real life socket situation.

    If my logic is wrong, someone please let me know.

    0 讨论(0)
提交回复
热议问题