Вопрос

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()
Это было полезно?

Решение

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:

  • Wait until you try to read the socket and fail, then take the appropriate action.
  • Use 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.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top