Возможно, у кого-то здесь будет ответ на эту вещь, которая просто сводит меня с ума.
Чтобы упростить это, я делаю своего рода прокси.Всякий раз, когда он что-то получает, он пересылает все на сервер и отправляет ответ.Таким образом, существует один сокет, всегда прослушивающий порт 4557 для клиентов, и для каждого входящего соединения на произвольном порту создается новый сокет для подключения к порту 4556 сервера.
Клиенты <==> Прокси-сервер <==> Сервер
Также есть еще один сокет, который создается и прослушивает запросы, поступающие с сервера и пересылаемые соответствующему клиенту.
Вот пример:
- Клиент A подключается к прокси-серверу через порт 4557
- Прокси-сервер создает сокет для сервера на порту 4556
- Наряду с этим он создает сокет, прослушивающий порт 40100
- Клиент отправляет вещи, перенаправленные на сервер
- Клиент отключается.Закрыть клиентское соединение и сокет к серверу
- Через некоторое время сервер отправляет данные на прокси-сервер через порт 40100
- Все пересылается клиенту A (порт 40100 соответствует клиенту A)
- И так далее.
До сих пор в своих тестах я использовал простой скрипт на python для отправки уникального tcp-пакета на прокси-сервер, а также сервер дампа, показывающий полученные данные и возвращавший их обратно.
Таким образом, проблема в том, что когда соединение с прокси закрыто, соединение с сервером также должно быть закрыто с помощью «sock.close ()».Однако это, кажется, полностью игнорируется.Сокет остается как ESTABLISHED.
О коде сейчас.
Несколько замечаний.
- DTN и Node - соответственно сервер и клиенты.
- runCallback вызывается в цикле, пока поток не умирает.
- finalCallback вызывается, когда поток умирает.
- Связи между удаленными хостами (клиентом), портами прокси (дляСервер) и прокси хранятся в словарях: TCPProxyHostRegister (RemoteHost => Proxy), TCPProxyPortRegister (Port => Proxy), TCPPortToHost (Port => RemoteHost).
Первый класс - TCPListenerThread.Он просто прослушивает определенный порт и создает прокси-серверы (по одному для каждого клиента => пара серверов и сервер => пара клиентов) и пересылает им соединения.
class TCPListenerThread(StoppableThread):
def __init__(self, tcp_port):
StoppableThread.__init__(self)
self.tcp_port = tcp_port
self.sock = socket.socket( socket.AF_INET, # Internet
socket.SOCK_STREAM ) # tcp
self.sock.bind( (LOCAL_ADDRESS, self.tcp_port) )
self.sock.listen(1)
def runCallback(self):
print "Listen on "+str(self.tcp_port)+".."
conn, addr = self.sock.accept()
if isFromDTN(addr):
tcpProxy = getProxyFromPort(tcp_port)
if not tcpProxy:
tcpProxy = TCPProxy(host, True)
else:
host = addr[0]
tcpProxy = getProxyFromHost(host)
if not tcpProxy:
tcpProxy = TCPProxy(host, False)
tcpProxy.handle(conn)
def finalCallback(self):
self.sock.close()
Теперь появляется прокси-сервер TCP: он связывает удаленныйхост (клиент) с портом подключения к серверу.Если это соединение от нового Клиента, он создаст новый слушатель (см. Выше) для Сервера и создаст сокет, готовый пересылать все на Сервер.
class TCPProxy():
def __init__(self, remote, isFromDTN):
#remote = port for Server or Remote host for Client
self.isFromDTN = isFromDTN
self.conn = None
#add itself to proxy registries
#If listening from a node
if not isFromDTN:
#Set node remote host
self.remoteHost = remote
TCPProxyHostRegister[self.remoteHost] = self
#Set port to DTN interface + listener
self.portToDTN = getNewTCPPort()
TCPPortToHost[self.portToDTN] = self.remoteHost
newTCPListenerThread(self.portToDTN)
#Or from DTN
else:
self.portToDTN = remote
TCPProxyPortRegister[self.portToDTN] = self
self.remoteHost = getRemoteHostFromPortTCP(self.portToDTN)
def handle(self, conn):
print "New connection!"
#shouldn't happen, but eh
if self.conn != None:
self.closeConnections()
self.conn = conn
#init socket with remote
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if self.isFromDTN:
self.sock.connect((self.remoteHost, 4556)) #TODO: handle dynamic port..
else:
self.sock.connect((DTN_Address, DTN_TCPPort))
#handle connection in a thread
self.handlerThread = newTCPHandlerThread(self)
#handle reply in a therad
self.replyThread = newTCPReplyThread(self)
def closeConnections(self):
try:
if self.conn != None:
print "Close connections!"
self.sock.close()
self.conn.close()
self.conn = None
self.handlerThread.kill()
self.replyThread.kill()
except Exception, err:
print str(err)
#pass
def forward(self, data):
print "TCP forwarding data: "+data
self.sock.send(data)
def forwardBack(self, data):
print "TCP forwarding data back: "+data
self.conn.send(data)
В этом прокси-классе я создаю экземплярдва класса, TCPHandlerThread и TCPReplyThread.Они отвечают за пересылку на сервер и пересылку обратно клиенту соответственно.
class TCPHandlerThread(StoppableThread):
def __init__(self, proxy):
StoppableThread.__init__(self)
self.proxy = proxy
def runCallback(self):
test = False
while 1:
data = self.proxy.conn.recv(BUFFER_SIZE)
if test:
self.proxy.sock.close()
test = True
if not data:
break
print "TCP received data:", data
self.proxy.forward(data)
self.kill()
def finalCallback(self):
self.proxy.closeConnections()
class TCPReplyThread(StoppableThread):
def __init__(self, proxy):
StoppableThread.__init__(self)
self.proxy = proxy
def runCallback(self):
while 1:
data = self.proxy.sock.recv(BUFFER_SIZE)
if not data:
break
print "TCP received back data: "+data
self.proxy.forwardBack(data)
self.kill()
def finalCallback(self):
self.proxy.closeConnections()
Вы видите, что всякий раз, когда соединение закрывается, поток умирает, а другое соединение (клиент / сервер с прокси или прокси сСервер / Клиент) должны быть закрыты в Proxy.closeConnections ()
Я заметил, что когда closeConnections () имеет значение «data = self.proxy.conn.recv (BUFFER_SIZE)», все идет хорошо, но когда он вызываетсядаже сразу после последнего утверждения все идет не так.
Я подключил протокол TCP, и прокси-сервер не посылает никакого "пока сигнала".Состояние сокета не переходит в TIME_WAIT или что-либо еще, оно просто остается УСТАНОВЛЕННЫМ.
Кроме того, я протестировал его в Windows и Ubuntu.
- В Windows все идет именно так, как я объяснил
- В Ubuntu он обычно работает нормально (не всегда), 2 соединения, и в третий раз, когда я подключаюсь к одному и тому же клиенту точно так же, как прокси, он снова идет не так, как описано.
Вот три файла, которые я использую, чтобы вы могли взглянуть на весь код.Мне жаль, что файл прокси не может быть действительно легко читаемым.Предполагалось, что это быстрая разработка.
http://hognerud.net/stackoverflow/
Заранее спасибо ..Это конечно что-то глупое. Пожалуйста, не бей меня слишком сильно, когда увидишь: (