Сокеты и межобщинное общение между потоками - PullRequest
1 голос
/ 17 июня 2011

Я использую многопоточный 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()

Ответы [ 2 ]

1 голос
/ 17 июня 2011

Вы можете сделать ваши объекты потоков (если они есть) повторяемыми , и вы сделаете "широковещательную" функцию, которая просто перебирает ваши потоки и использует их сокеты для отправки информации.

Или, если у вас нет объекта на потоки, вы всегда можете просто иметь список сокетов и делать почти то же самое.

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

0 голосов
/ 17 июня 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...