2016-01-23 54 views
0

我只是不能設法添加多線程到我的UDP服務器。 第二個客戶端可以連接,但是當有人已經連接到服務器時,它會立即被拋出服務器。Python:UDP代理多線程

這可能是由SingleThreading以外的其他原因造成的嗎?

import sys, socket 
localPort, remoteHost, remotePort = sys.argv[1].split(':') 
try: 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind(('', localPort)) 
except: 
    fail('Failed to bind on port ' + str(localPort)) 

knownClient = None 
knownServer = (remoteHost, remotePort) 
sys.stderr.write('Ready.\n') 


while True: 
    data, addr = s.recvfrom(32768) 
    print addr 
    if knownClient is None: 
     knownClient = addr 
    if addr == knownClient: 
     try: 
      s.sendto(data, knownServer) 
     except: 
      pass 
    else: 
     try: 
      s.sendto(data, knownClient) 
     except: 
      pass 

回答

0

你不能寫一個只有端口的UDP代理。您應該如何從服務器的答案中知道您應該向哪個連接的客戶端發送答案。您必須爲每個客戶端打開一個到遠程服務器的新套接字。

+0

我很抱歉,但我是新來的Python。你能給我舉個例子怎麼做嗎? – juggernawt

0

這不是Python,而是「網絡」,當然不是「多線程」。您需要將客戶端引導到不同的端口,或者爲每個新的客戶端連接創建一個新的傳出套接字。

因爲你有多個套接字,一個非常有效的方法是坐在select並等待來電。

爲了識別客戶端,還需要保留新套接字用於與服務器通信的本地地址的引用。

重新編寫代碼,在每個新的傳入客戶端連接上打開socket。沒有保證,因爲這將涉及針對未知情況(您的)的網絡測試。

對於一個非常健壯的實現,你必須添加錯誤檢查,插座取消對不見了連接...

import select 
import socket 
import sys 


localPort, remoteHost, remotePort = sys.argv[1].split(':') 

try: 
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    server.bind(('', localPort)) 
except: 
    fail('Failed to bind on port ' + str(localPort)) 

localaddr = s.getsockname() # (localhost, localport) 
remaddr = (remoteHost, remotePort) 

sys.stderr.write('Ready.\n') 

allsockets = [server] 

proxysocks = dict() 
origins = dict() 


while True: 
    toread, _, _ = select.select(allsockets, [], []) 

    s = toread[0] # 1st socket available to read 
    data, orig = s.recvfrom(32768) # data, (remhost,remport) 
    dest = s.getsockname() # (localhost, localport) 

    if dst == localaddr: # client -> localserver 
     try: 
      p = proxysocks[orig] # find proxy sock 
     except KeyError: # new client connection 
      proxysocks[orig] = p = socket.socket(socket.AF_INET, 
               socket.SOCK_DGRAM) 

      proxyaddr = p.getsockname() # keep local address of new socket 
      origins[proxyaddr] = orig # link proxyaddr -> clientaddr 

      allsockets.append(p) # make it "selectable" 

     p.sendto(remaddr, data) # send to server 

    else: # server -> proxyaddr 
     s.sendto(origins[dstaddr])