È possibile ottenere in modo affidabile un socket Winsock su connect()
se si connette a localhost con una porta nell'intervallo di porte temporanee assegnate automaticamente (5000-65534). In particolare, Windows sembra avere un numero di porta a rotazione a livello di sistema che è la porta successiva che tenterà di assegnare come numero di porta locale per un socket client. Se creo i socket fino a quando il numero assegnato è appena sotto il mio numero di porta di destinazione, quindi creo ripetutamente un socket e tento di connettermi a quel numero di porta, di solito riesco a connettere il socket a se stesso.Perché un socket può connettersi() alla propria porta effimera?
Prima ho verificato che si verifichi in un'applicazione che tenta ripetutamente di connettersi a una determinata porta su localhost e, quando il servizio non è in ascolto, stabilisce molto raramente una connessione e riceve il messaggio inviato inizialmente (cosa che accade essere un comando Redis PING
).
Un esempio, in Python (gestito con niente ascolto della porta di destinazione):
import socket
TARGET_PORT = 49400
def mksocket():
return socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
while True:
sock = mksocket()
sock.bind(('127.0.0.1', 0))
host, port = sock.getsockname()
if port > TARGET_PORT - 10 and port < TARGET_PORT:
break
print port
while port < TARGET_PORT:
sock = mksocket()
err = None
try:
sock.connect(('127.0.0.1', TARGET_PORT))
except socket.error, e:
err = e
host, port = sock.getsockname()
if err:
print 'Unable to connect to port %d, used local port %d: %s' % (TARGET_PORT, port, err)
else:
print 'Connected to port %d, used local port %d' (TARGET_PORT, port)
Sulla mia macchina Mac, questo alla fine termina con Unable to connect to port 49400, used local port 49400
. Sulla mia macchina Windows 7, una connessione viene stabilita con successo e stampa Connected to port 49400, used local port 49400
. Il socket risultante riceve tutti i dati che gli vengono inviati.
Si tratta di un bug in Winsock? È un bug nel mio codice?
Edit: Ecco uno screenshot del TcpView con il collegamento incriminato mostrato:
Ecco alcune domande correlate: http://stackoverflow.com/questions/4949858/how-can-you-have-a-tcp-connection-back-to-the-same-port http: // stackoverflow. it/questions/5139808/tcp-simult-open-and-self-connect-prevention –
Ho questo problema che si verifica abbastanza regolarmente nei miei sistemi, che coinvolgono almeno cinque porte locali su cui i server possono o non possono essere in esecuzione ea cui i clienti cercano continuamente di connettersi. Non riesco a pensare ad alcun modo per risolvere questo in modo indipendente dalla piattaforma a livello di connessione. –