гнездо python висит на коннекте - PullRequest
4 голосов
/ 27 августа 2011

Я пытаюсь сделать прозрачный прокси в Python, используя модуль сокета. но по какой-то причине он зависает при подключении () к сокету. вот код, который я использую:

from __future__ import division
import socket
import struct
#import mcpackets
import sys
import time
#CUSTOM SETTINGS
HOST="192.168.178.28"
PORT=25565
#END CUSTOM SETTINGS

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('',25565))
serversocket.listen(1)
print "waiting for client, press multiplayer and use 'localhost' as server"
clientsocket,address=serversocket.accept()
print "client connected from %s:%d"%address
serversocket.close()
print "connecting to '%s:%d'"%(HOST,PORT)
serversocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "socket created."
serversocket.connect((HOST,PORT))#------------------------------ freezes here
print "socket connected."
serversocket.settimeout(0)
clientsocket.settimeout(0)
print "timeouts set."
print "now proxying."
#tdata=[]
try:
    while(True):
        dat=None
        try:
            dat=clientsocket.recv(4096)
        except socket.timeout:
            pass

        if(dat!=None):
            try:
                serversocket.send(dat)
            except socket.timeout:
                pass
        #vice versa
        dat=None
        try:
            dat=serversocket.recv(4096)
        except socket.timeout:
            pass
        if(dat!=None):

            try:
                clientsocket.send(dat)
            except socket.timeout:
                pass
except:
    clientsocket.close()
    #with open("data.log","w") as fid:
    #    fid.write(''.join(tdata))
    raise

проблема не в сети, так как подключение к серверу напрямую работает нормально. есть идеи о том, что идет не так?

Ответы [ 2 ]

5 голосов
/ 27 августа 2011

Это часть реализации сокетов TCP, когда операционная система отказывается разрешить новое соединение сокетов после того, как сокет с тем же именем был недавно отключен.

Чтобы форсировать этот запрос, установите опцию сокета REUSEADDR на вашем сокете, прежде чем подключать его (для обоих созданий сокетов вашего сервера):

serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Таким образом, после закрытия первого сокета сервера, когда вы хотите подключить новый сокет сервера (с тем же хостом, портом), ОС не откажется.

1 голос
/ 27 августа 2011

Мне трудно воспроизвести это, поскольку он не зависает на Mac OS X или Windows 7 с Python 2.7. Поэтому, не имея возможности воспроизвести, я предполагаю, что есть проблема с повторным использованием serversocket, так что вскоре после его закрытия в вашей ОС. Закрытие сокета переводит этот сокет в состояние TIME_WAIT, поэтому он не закрывается немедленно. Время, необходимое для реального закрытия сокета, зависит от операционной системы и может быть причиной вашей проблемы.

Хотя люди, похоже, рекомендуют не использовать его, вы можете использовать опцию SO_LINGER, чтобы принудительно закрыть сокет.

Например:

l_onoff, l_linger = 1, 1 # send RST (hard reset the socket) after 1 second
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
                        struct.pack('ii', l_onoff, l_linger))
# this should now complete after l_linger timeout
serversocket.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...