2016-01-23 45 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])