2016-12-11 2 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 в моем конкретном случае? Не было бы более эффективно/просто отправить поток в подпитку и запрос в другой?

EDIT: Наконец, я использовал суб-нить для потока

+0

FWIW, нити в питон примерно просто удобство, а не эффективность (с некоторыми исключениями, например, вызов C модули, которые явно освобождают GIL). – spectras

ответ

1

я предлагаю вам попробовать gevent, простой в understant АНИ, его хорошо, чтобы идти, если вы хотите, чтобы преодолеть эту проблему , есть раздел о 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

Если вы хотите обработать новые входящие клиенты, при обработке одного клиента, да. Но тогда было бы проще использовать потоки или некоторую асинхронную библиотеку. – Daniel

Смежные вопросы