2011-06-17 5 views
1

J'utilise Multithreaded TCP Server. Chaque socket est créé en tant que thread distinct pour chaque client. Je voudrais envoyer des données à tous les clients via la méthode de socket send(). Le problème que je suis confronté ici est, il envoie des données au fil courant (à partir de laquelle il a reçu) seulement.Sockets & Inter communication parmi les threads

Je n'ai pas trouvé de bonne documentation pour la communication inter-thread pour Python.

Toute solution à mon problème afin que je puisse envoyer des données à tous les clients.

Merci.

#!/usr/bin/env python 

    """ 
    A server with multithreading to handle multiple clients. 
    """ 

    import select 
    import socket 
    import sys 
    import threading 
    import logging 
    import datetime 

    class Server: 
     def __init__(self): 
      self.host = '' 
      self.port = 25000 
      self.backlog = 5 
      self.size = 1024 
      self.server = None 

     def open_socket(self): 
      try: 
       self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
       self.server.bind((self.host,self.port)) 
       self.server.listen(5) 
       lc.append(self.server) 
      except socket.error, (value,message): 
       if self.server: 
        self.server.close() 
       print "Could not open socket: " + message 
       sys.exit(1) 

     def run(self): 
      self.open_socket() 
      input = [self.server,sys.stdin] 
      running = 1 
      while running: 
       inputready,outputready,exceptready = select.select(input,[],[]) 

       for s in inputready: 
        if s == self.server: 
         c = Client(self.server.accept()) 
         c.start() 
         threads.append(c) 

      # close all threads 
      self.server.close() 
      for c in threads: 
       c.join() 

    class Client(threading.Thread): 
     def __init__(self,(client,address)): 
      threading.Thread.__init__(self) 
      self.client = client 
      self.address = address 
      self.size = 1024 
      dc[address[0]]=client#address[1] 
      logging.info('%s added successfully...',address[0]) 


     def run(self): 
      running = 1 
      print dc 
      while running: 
       data = str(self.client.recv(self.size)) 
       #print dc 

       if data.strip() == '0x01': 
        sendtoAll() 
       elif data.strip() == '0x02': 
        self.client.send("version"+data) 
       elif data.strip() == '0x03':#return current time 
        print datetime.datetime.now() 
        self.client.send(str(datetime.datetime.now())) 
       else: 
        self.client.send("empty") 
        #self.client.close() 
        #running = 0 
def sendtoAll(): 
     for i, sock in dc.items(): 
      print "Address:Sockets = ", i,sock 
      try: 
       print "sending to %s by Thread "%i 
       sock.send("data"+str(threading.current_thread().getName())) 
      except socket.error,e: 
       print "error socket %s\n" % e 
       sock.close() 
       del lc[i] 

if __name__ == "__main__": 
     dc={}  #dict to store ip-address:scokets pair 
     lc=[]  #tuples to store all sockets 
     threads=[] #holds threads 
     logging.basicConfig(level=logging.INFO) 
     logging.info('Starting Server Object...') 
     s = Server() 
     s.run() 

et le code client est

import socket 
import sys 

host = '192.168.1.4' 
port = 25000 
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((host,port)) 
sys.stdout.write('%') 

while 1: 
    # read from keyboard 
    line = sys.stdin.readline() 
    if line == '\n': 
     break 
    s.send(line) 
    data = s.recv(size) 
    sys.stdout.write(data) 
    sys.stdout.write('\n%') 
s.close() 

Répondre

0

Une socket TCP est l'un des deux points d'extrémité. Il n'y a pas de "diffusion" dans TCP. Si vous voulez envoyer un seul message à tous vos clients, vous devrez l'envoyer à chacun d'entre eux individuellement.

Si vous utilisez un conteneur approprié pour tous vos objets clients, il ne vous reste plus qu'à faire des itérations, en envoyant votre message à chacun d'entre eux.

+0

Je n'ai pas dit que je voulais diffuser. Si vous voyez le code attentivement, vous constaterez que j'envoie une boucle à chaque socket (juste le nom fn est diffusé). Mais le message est envoyé à une socket à la fois. le problème persiste. Le message est actuellement mis en file d'attente pour le thread non courant et remis lorsque ce thread est appelé à nouveau. –

+1

@Pujan Srivasta: Si vous utilisez des sockets TCP, vous devez les envoyer une socket à la fois. Vous ne pouvez pas envoyer plusieurs sockets "en même temps" et vous ne pouvez pas vous connecter à plusieurs clients par socket. La seule façon d'envoyer à plusieurs clients en une fois est diffusée (en fait, diffusée ou en multidiffusion), mais cela ne fonctionne qu'avec UDP. Assurez-vous également que vous n'obstruez pas le socket pour le client précédent lorsque vous enregistrez le socket pour le nouveau client. – Vatine

+0

Merci Vatine, je ne savais pas que je ne peux pas utiliser plusieurs socket à la fois. En fait, je vais utiliser le code ci-dessus parmi les différents réseaux (globalement routable) où Multicast ne sera pas disponible bien sûr. Pensez-vous que l'UDP est un bon choix? ou toute solution merci. –

1

Vous pouvez faire des objets vos threads (le cas échéant) iterable et vous faire une fonction « diffusion » qui vient itérer vos fils et utiliser leurs prises pour envoyer l'information.

Si vous n'avez pas d'objet par thread, vous pouvez toujours avoir une liste de sockets et faire à peu près la même chose.

Assurez-vous que vous utilisez les verrous correctement en fonction de vos besoins (soit pour l'ensemble de la prise ou chaque prises individuelles)