2016-12-11 98 views
0

我正在一個連續發送數據到客戶端的服務器上工作。該客戶端也可以與發送特定請求的服務器交互守時。我寫了一個守護進程來做到這一點。請注意,這個守護進程在一個線程中工作。現在,腳本結構如下:Python,通過兩個套接字進行通信

class MyDaemon(threading.Thread): 

    def __init__(self): 

     # Init Stream socket (output) 
     self.MainSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.MainSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     self.MainSock.bind(('', 15555)) 
     self.MainSock.listen(5) 
     self.MainSock.setblocking(0) 

     # Init Request socket (input) 
     self.RequestSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.RequestSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     self.RequestSock.bind(('', 15556)) 
     self.RequestSock.listen(5) 
     self.RequestSock.setblocking(0) 


    def run(self): 

     while True: 

      # Listen to connection on MainSock 
      try: 
       self.stream, address = self.MainSock.accept() 
      except: 
       pass 

      # Listen to connection on RequestSock 
      try: 
       self.request, address = self.RequestSock.accept() 
      except: 
       pass 

      if self.stream: 
       send_message_continuously() # it is a stream 

      if self.request: 
       recv_a_message_from_client() 
       do_whatever_action_the client_request() 

的問題是:

  • 只用蒸籠,一切工作正常。

  • 只使用請求者,一切正常。

  • 使用兩個插座同時阻擋流光。

我看到一個線程無法同時連接(或連接)到兩個套接字。我還讀到,使用select模塊可能有助於處理這種問題,但我從來沒有使用過它,並且我對在特定情況下使用它有點失落。

什麼是更有效的方式來處理這個問題? 如何在我的特殊情況下設置select? 將發送到子線程並將請求發送到另一個會更高效/簡單嗎?

編輯:最後,我用了一個子線程的

+0

FWIW,在Python線程是關於一種單純的方便,而不是效率(有一些例外,如調用C明確釋放GIL的模塊)。 – spectras

回答

1

我建議你去嘗試gevent,簡單understant的API,它的好走,如果你想克服的問題,有一個關於servers 的部分了解tcp通信&重新考慮你當前的解決方案。
代碼卡 -

def handle(socket, address): 
    print('new connection!') 

server = StreamServer(('127.0.0.1', 1234), handle) # creates a new server 
server.start() # start accepting new connections 

希望你能花更多的時間提出申請未做skelts。 :)

2

當使用select你必須測試,你的兩個插座的準備接受:

def run(self): 
    while True: 
     ready, _, _ = select.select([self.MainSock, self.RequestSock],[],[]) 
     for sock in ready: 
      if sock is self.MainSock: 
       send_message_continuously(sock.accept()) 
      elif sock is self.RequestSock: 
       recv_a_message_from_client(sock.accept()) 
+0

客戶端是否也必須使用'select'? –

+0

如果您想處理新的傳入客戶端,同時處理一個客戶端,是的。但是,使用線程或一些asyncio庫會更容易。 – Daniel

相關問題