Сокеты и межобщинное общение между потоками

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()
Теги:
multithreading
networking

2 ответа

0
Лучший ответ

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

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

  • 0
    Я не сказал, что хочу вещать. Если вы внимательно посмотрите код, вы обнаружите, что я посылаю через цикл в каждый сокет (просто имя fn передается). Но сообщение отправляется в один сокет за один раз. проблема сохраняется. Сообщение фактически ставится в очередь для не текущего потока и доставляется при повторном вызове этого потока.
  • 1
    @Pujan Srivasta: Если вы используете TCP-сокеты, вы должны отправлять его по одному сокету за раз. Вы не можете отправлять несколько сокетов «одновременно» и не можете подключиться к более чем одному клиенту на сокет. Единственный способ отправить нескольким клиентам за один раз - широковещательная (на самом деле, широковещательная или многоадресная), но это работает только с UDP. Кроме того, убедитесь, что вы не засоряете сокет для предыдущего клиента, когда сохраняете сокет для нового клиента.
Показать ещё 3 комментария
1

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню