2011-08-27 122 views
3

我想在python中使用套接字模塊做一個透明代理。但由於某種原因,它掛在connect()插座上。這裏是我使用的代碼: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 

問題不在於網絡,因爲連接到服務器直接工作正常。有什麼錯誤的想法?

回答

1

我很難再現這個問題,因爲它似乎沒有在Python 2.7或Mac OS X或Windows 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() 
3

這是TCP套接字實現的一部分,其中操作系統拒絕讓具有相同名稱的插座後,新的套接字連接已斷開最近。

爲了迫使這一要求,REUSEADDR套接字選項的插座上,將其連接前設置(爲您的服務器套接字的創作):後

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

這樣你閉上你的第一臺服務器插槽,當你想連接你的新服務器套接字(使用相同的主機,端口)時,操作系統不會拒絕。

+2

這適用於'bind()'。作者說它凍結在'connect()'上。這可能意味着'connect()'掛斷了IP地址,或者服務器沒有響應'SYN + ACK'。 –

+0

應該給出一個已經在使用中的地址例外。 – doxin