2015-07-15 3 views
0

Я создаю сервер python, который должен обрабатывать соединение с удаленными узлами на порту 9090 и соединение только с localhost (данные отправки графического интерфейса) на порт 9091. Я думаю, что проблема в том, что в socket.listen (backlog), потому что это блокирует все. Итак, есть способ запустить socket1.listen (backlog) и socket2.listen (backlog) в одно и то же время? Кроме того, является ли хорошей идеей и, прежде всего, безопасным создание сокета для приема данных из графического интерфейса (написанного на Java)?Python, прослушивание на двух сокетах одновременно

+0

Почему бы не использовать нить? первый сокет не будет блокировать другой сокет. –

+0

Ваш вопрос несколько расплывчатый, но да, возможно, вам нужна другая нить, предпочтительно нить для каждого сокета. Попробуйте обернуть функциональность сокета в новом классе, наследуйте этот класс от Thread, а затем просто создайте новый экземпляр класса для каждого порта. – Dan

+0

Используете ли вы существующий веб-сервер python или пишете свой собственный? Я бы не использовал сокет для получения данных gui лично. Я думаю, что вы ищете «межпроцессные коммуникации», такие как D-Bus, XML-RPC и другие. – NuclearPeon

ответ

0

Это может быть сделано в C: Listen to multiple ports from one server

и C++: Create multiple listening sockets

так что вы должны быть в состоянии сделать это в Python.

Единственное, что сделало бы это небезопасным, - это то, что ваш сервер выполняет опасную деятельность в ответ на графический интерфейс, но вы, вероятно, можете добавить код для проверки и защиты от хаков.

+0

Есть вероятность, что кто-то подделает свой IP-адрес в 127.0.0.1 и отправит данные на сервер Python, претендуя на роль графического интерфейса? –

+0

Нет, это специальный адрес «loopback», который работает только на одном компьютере. –

0

Я использую python2.7.3, и, как указано в моем комментарии, я не смог воспроизвести проблему блокировки listen. Примечание:

  • ради простоты я только с помощью IPv4 розетки
  • Я включил Python «s суфлера в коде, чтобы показать, что он не блокировал
  • относительно возможных проблем безопасности: сокет (s_local) прослушивает 9091, принимает соединения только с локального хоста (от других хостов и не будет работать)

Вот отрывок из в CentOS5 Машина:

>>> import socket 
>>> s_global = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
>>> s_global.bind(("", 9090)) 
>>> backlog = 0xFF 
>>> s_global.listen(backlog) 
>>> s_local = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
>>> s_local.bind(("127.0.0.1", 9091)) 
>>> s_local.listen(backlog) 
>>> 

и вот некоторые выходы на ту же машину:

netstat -an | grep 909 
tcp  0  0 0.0.0.0:9090    0.0.0.0:*     LISTEN  
tcp  0  0 127.0.0.1:9091    0.0.0.0:*     LISTEN  

Как видно, как сервер сокетов прослушивания подключений.

Теперь, если что-то не так в моих условиях (некоторые чтения показали, что по умолчанию сокеты являются блокировка по умолчанию), после создания каждого сокета, можно добавить (как указано в одном из комментариев) следующую строку (ы):

  • для s_global

    s_global.setblocking(0) 
    
  • для s_local

    s_local.setblocking(0) 
    

Теперь для того, чтобы принимать входящие соединения с обоих сокетов, вы должны использовать Python «s select module (используется для асинхронной IO) без необходимости для других потоков; приложение-сервер должен постоянно прослушивать соединения, что-то вроде:

TIMEOUT = 1 #seconds 
terminate = False # variable to be modified externally to end the loop 
listening_sockets = [s_global, s_local] 
while (not terminate): 
    notified_socket_list = select.select(listening_sockets, [], [], TIMEOUT)[0] 
    for notified_socket in notified_socket_list: 
     incoming_socket, addr = notified_socket.accept() 
     handle(incoming_socket, addr) 

Примечание: стоит упоминания: Epoll (select.epoll) является производительность мудрый предпочтительнее выбрать (select.select), но я не пробовал все же.

Теперь, касательно функции обработки соединений (handle): если ваш сервер разработан только для образовательных целей, вы можете оставить его как есть, но если ваш сервер предназначен для приема большого количества одновременных подключений и большого количества обмен данными с/каждому клиенту, вы должны обрабатывать каждое соединение в отдельной строке (это общий совет, который не применяется к Python из-за его GIL, иногда потоки только замедляют работу)/процесс как выполненный в SocketServer.py - part of Python's standard library.

@ Edit1 - ответ на 1-й комментарий:

Это просто, все, что вам нужно сделать, это изменить немного в внутреннийfor петля:

for notified_socket in notified_socket_list: 
     incoming_socket, addr = notified_socket.accept() 
     if notified_socket == s_global: 
      handle_global(incoming_socket, addr) 
     else: 
      handle_local(incoming_socket, addr) 

или вы можете использовать свое оригинальное решение и выполните различие в соединениях в ручке: аргумент addr содержит (локальный) порт, к которому подключен сокет; вы можете проверить его и в зависимости от его значения (9090 или 9091) обрабатывать соединение по-разному.

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