2011-06-17 58 views
1

我正在使用多線程TCP服務器。 每個套接字都作爲每個客戶端的單獨線程創建。我想通過套接字的send()方法將數據發送到所有客戶端。我在這裏面臨的問題是,它僅將數據發送到當前線程(從中收到)。線程之間的套接字和內部通信

我無法找到Python的內部線程通信的良好文檔。

我的問題的任何解決方案,以便我可以發送數據到所有客戶端。

謝謝。

#!/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() 

和客戶端代碼是

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() 

回答

0

TCP套接字是兩個端點之一。 TCP中沒有「廣播」這樣的東西。如果你想發送一條消息給你的所有客戶,你將不得不單獨發送給每一個客戶。

如果您爲所有客戶端對象使用合適的容器,那麼它只是一個遍歷此問題的事情,將消息發送給每個客戶端對象。

+0

我沒有說我想播放。如果您仔細查看代碼,您會發現我通過循環發送到每個套接字(只是名稱被廣播)。但消息一次發送到一個套接字。問題依然存在。 消息實際上是排隊等待非當前線程並在該線程再次被調用時遞送。 – 2011-06-17 11:10:59

+1

@Pujan Srivasta:如果您使用TCP套接字,您必須一次將它發送一個套接字。您無法一次發送多個套接字,也無法連接到每個套接字的多個客戶端。一次發送到多個客戶端的唯一方法是廣播(實際上是廣播或多播),但只適用於UDP。另外,在保存新客戶端的套接字時,請確保沒有爲先前的客戶端打開套接字。 – Vatine 2011-06-17 11:19:36

+0

謝謝Vatine,我不知道我不能一次使用多個套接字。實際上,我將在多播不能使用的不同網絡(全球可路由)之間使用上述代碼。你認爲UDP是不錯的選擇嗎?或任何解決方案謝謝。 – 2011-06-17 11:25:38

1

你可以讓你的線程對象(如果有的話)iterable和你做一個「廣播」功能,只需通過你的線程迭代,並使用自己的套接字發送信息。

或者,如果你沒有每個線程的對象,你總是可以擁有一個套接字列表,並做幾乎相同的事情。

確保您正確使用根據您的需求鎖(無論是對所有的插座或每個單獨的插座)