Non-blocking connect
Roy Smith
roy at panix.com
Fri May 2 14:03:47 EDT 2008
In article
<59915ad0-2af1-4903-8ffd-48da2ce4e647 at y22g2000prd.googlegroups.com>,
mp <mailpitches at email.com> wrote:
> Code is at bottom. Basically, if I turn off socket blocking prior to
> connecting, I get a "Socket is not connected" error when I try to send
> data. However, if I do not turn off blocking, OR if I place a print
> statement anywhere before the send call, it works! WTF?
>
> I'd like to understand what's going on in the background here, if you
> know don't skimp on the details.
>
> Thanks
>
> ---------------------------------------------------------------
> import
> socket
> sock = socket.socket(socket.AF_INET,
> socket.SOCK_STREAM)
> sock.setblocking(0)
> sock.connect_ex(('localhost',
> 9000))
> sock.setblocking(1)
> sock.send('foo')
> sock.close()
I can't be 100% sure about this because I don't know what's running on your
port 9000 that you're trying to connect to, but I think I know what's going
on.
I just tried your code, but changed 9000 to 22 (ssh). What I found is that
if you eliminate the setblocking(0) call, the connect_ex() call returns 0,
indicating it succeeded. If you leave the setblocking(0) call in,
connect_ex() returns EINPROGRESS (Operation now in progress). This makes
sense. Here's the code:
import socket
import os
import errno
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
err = sock.connect_ex(('localhost', 22))
print errno.errorcode[err], os.strerror(err)
When you do a TCP connect, there is what's called a three-way handshake
that happens between the TCP stacks at the two ends of the connection. I
send a packet with the SYN bit set, you respond with a packet with both SYN
and ACK set, and I respond with an ACK. Even when both ends are on the
same box (i.e. localhost), this has to happen.
Quoting from http://docs.python.org/lib/socket-objects.html:
> Some notes on socket blocking and timeouts: [...] In non-blocking mode,
> operations fail (with an error that is unfortunately system-dependent) if
> they cannot be completed immediately.
Since the three-way handshake can't be completed immediately, the
connect_ex call fails when you try it in non-blocking mode.
So, that's the explanation. Now the question: What are you trying to do
that you need non-blocking mode? Or are you just experimenting to see what
happens?
BTW, this was done on an OSX-10.5.2 box, but I think the result would be
essentially the same on any platform.
More information about the Python-list
mailing list