This question is not limited to Python. Its a general socket question. I have a non-blocking socket and want to connect to a machine which is reachable - on the other side the port does not exist. Why does select(...) succeed anyway? I expected a timeout. sock.send(...) fails with a broken pipe. How can I determine if the socket is really connected after select(...)? Thanks in advance.
import socket, errno, os, time, select
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
err = sock.connect_ex(('192.168.178.21', 12345))
ready_to_read, ready_to_write, in_error = select.select([], [sock], [], timeout=5)
#ready_to_write is set even 192.168.178.21:12345 does not exist.
sock.setblocking(1)
sock.send('foo') #this fails
sock.close()
How do you check socket is connected or not? If you need to determine the current state of the connection, make a nonblocking, zero-byte Send call. If the call returns successfully or throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected.
On a blocking socket, the return value indicates success or failure of the connection attempt. With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR , and WSAGetLastError() will return WSAEWOULDBLOCK.
To mark a socket as non-blocking, we use the fcntl system call. Here's an example: int flags = guard(fcntl(socket_fd, F_GETFL), "could not get file flags"); guard(fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK), "could not set file flags"); Here's a complete example.
If the blocking mode is set for a socket, the calling program is suspended until the expected event completes. If nonblocking is set by the FCNTL() or IOCTL() calls, the calling program continues even though the I/O call might not have completed.
Try checking the return values. Here's what I get in a similar situation:
>>> import socket, errno, os, time, select
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.setblocking(0)
>>> err = sock.connect_ex(('10.0.0.1', 12345))
>>> import errno
>>> print errno.errorcode[err]
EINPROGRESS
>>> print sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
61
>>> print errno.errorcode[61]
ECONNREFUSED
The select()
call is probably returning because there was an exceptional condition on the socket - that is, its connection was refused.
If I do this, the select()
returns immediately:
>>> ready_to_read, ready_to_write, in_error = select.select([], [sock], [])
And interestingly enough, the return values match exactly what you passed in (if you had more than one socket, that would likely be different):
>>> print in_error
[]
>>> print ready_to_read
[]
>>> print ready_to_write
[<socket._socketobject object at 0x10ccd0980>]
The designers of select()
are expecting you to run select()
in a loop, and if a socket returns an error when you attempt the write, remove it from the list when the write fails.
So you have a couple of options, off the top of my head:
getsockopt()
as I did above to check if the socket is OK, or is in an error state, before attempting to do anything with it.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With