Arhn - архитектура программирования

Сокеты и взаимодействие между потоками

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

Ответы:


1

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

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

17.06.2011
  • Я не говорил, что хочу транслировать. Если вы внимательно посмотрите код, вы обнаружите, что я отправляю через цикл в каждый сокет (транслируется только имя fn). Но сообщение отправляется в один сокет за раз. проблема сохраняется. Сообщение фактически ставится в очередь для не текущего потока и доставляется при повторном вызове этого потока. 17.06.2011
  • @Pujan Шриваста: Если вы используете сокеты TCP, вы должны отправлять их по одному сокету за раз. Вы не можете отправлять данные сразу в несколько сокетов и не можете подключаться более чем к одному клиенту на сокет. Единственный способ отправить нескольким клиентам за один раз — это широковещательная рассылка (на самом деле, широковещательная или многоадресная), но она работает только с UDP. Кроме того, убедитесь, что вы не забиваете сокет для предыдущего клиента, когда сохраняете сокет для нового клиента. 17.06.2011
  • Спасибо, Ватин, я не знал, что я не могу использовать несколько сокетов одновременно. На самом деле я буду использовать приведенный выше код в разных сетях (глобально маршрутизируемых), где многоадресная рассылка, конечно же, не будет доступна. Считаете ли вы UDP хорошим выбором? или любое решение спасибо. 17.06.2011
  • Вы можете использовать несколько сокетов, но вы не можете хранить два сокета в одной переменной. Как правило, вам потребуется открыть сокет для приема входящих запросов ОДИН РАЗ, выполнить прослушивание (это делает сидячий режим готовым к приему соединений), затем использовать выбор или принятие (первый для проверки наличия входящего соединения; последний блокирует до тех пор, пока связь есть). Каждый вызов accept возвращает новый сокет, сохраните их в списке или что-то в этом роде. 17.06.2011
  • Этот ответ, кажется, имеет мало общего с заданным вопросом. Комментарии также имеют очень мало смысла; код OP хранит словарь со всеми клиентскими подключениями и перебирает его, чтобы отправить сообщение каждому. 18.06.2011

  • 2

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

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

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

    17.06.2011
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..