2014-11-26 2 views
3

Это моя серверная программа, как она может отправлять данные, полученные от каждого клиента, каждому другому клиенту?Мне нужен сервер для отправки сообщений всем клиентам (Python, сокеты)

import socket 
import os 
from threading import Thread 
import thread 

def listener(client, address): 
    print "Accepted connection from: ", address 

    while True: 
     data = client.recv(1024) 
     if not data: 
      break 
     else: 
      print repr(data) 
      client.send(data) 

    client.close() 

host = socket.gethostname() 
port = 10016 

s = socket.socket() 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
s.bind((host,port)) 
s.listen(3) 
th = [] 

while True: 
    print "Server is listening for connections..." 
    client, address = s.accept() 
    th.append(Thread(target=listener, args = (client,address)).start()) 

s.close() 
+0

Не пытайтесь опубликовать код Python как фрагмент кода запуска; что работает только для JS/HTML/CSS. (На этот раз я отредактировал его.) – abarnert

+0

Как примечание, ваш код имеет сочетание вкладок и пробелов. Это действительно плохая идея; это может легко привести к тому, что Python не понимает структуру блока так же, как вы или другой человек. Вы должны рассмотреть возможность переключения на редактор, который поможет вам избежать этой проблемы, а также запустить скрипт с помощью 'python -t' или' python -tt', чтобы убедиться, что вы его исправили и не воссоздали. – abarnert

+1

Пожалуйста, взгляните на этот SO принятый ответ [Python SocketServer: отправка нескольким клиентам?] (Http://stackoverflow.com/questions/3670127/python-socketserver-sending-to-multiple-clients), возможно, это точно что вы ищете, особенно со всеми предложенными пунктами @abarnert, которые рассматриваются в небольшом примере реализации. – Anzel

ответ

6

Если вам нужно отправить сообщение всем клиентам, вам необходимо каким-то образом сохранить коллекцию всех клиентов. Например:

clients = set() 
clients_lock = threading.Lock() 

def listener(client, address): 
    print "Accepted connection from: ", address 
    with clients_lock: 
     clients.add(client) 
    try:  
     while True: 
      data = client.recv(1024) 
      if not data: 
       break 
      else: 
       print repr(data) 
       with clients_lock: 
        for c in clients: 
         c.sendall(data) 
    finally: 
     with clients_lock: 
      clients.remove(client) 
      client.close() 

Это, вероятно, будет понятнее фактор части этого в отдельные функции, как broadcast функции, он сделал все посылы.

Во всяком случае, это простейший способ сделать это, но у него есть проблемы:

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

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


Как Anzel указывает, что есть разные способ создания серверов, кроме использования потока (или двух) для каждого клиента: с использованием reactor, который мультиплексирует все события клиентов.

Python 3.x имеет некоторые большие библиотеки для этого встроенный, но 2,7 имеет только неуклюжий и устарелый asyncore/asynchat и низкого уровня select.

Как говорит Анзель, Python SocketServer: sending to multiple clients имеет ответ, используя asyncore, что стоит прочитать. Но я бы на самом деле не использовал это. Если вы хотите написать сервер на базе реакторов в Python 2.x, я бы использовал лучшую стороннюю структуру, например Twisted, или нашел или написал очень простой, который находится непосредственно на select.

+0

, точно рассматривая проблемы ОП столкнется. – Anzel

+0

Спасибо за подробный ответ! – samrap

+0

удивительный обмен. – kta