Python UDP recvfrom() конкретный адрес

Проблема, которую я вижу с этим кодом, заключается в том, что, хотя он работает, некоторая информация, которую клиенты (игроки) отправляют на этот сервер, будет попадать в метод «разрешение», когда предполагается, что в конечном итоге в «clientRequests», потому что оба они имеют получено из(). Итак, если бы я мог указать, КАКОЙ адрес мне нужен, в качестве параметра recvfrom(), это решило бы это. Я считаю, что это возможно с C++, но с python и как? С TCP такой проблемы нет, но я предпочитаю UDP.

Что-то вроде: recvfrom(512, address=(ip, port)) ?

«разрешение» используется для обработки подключения новых клиентов.

Проблема будет заключаться в том, что такая информация, как позиции, события, отправленные клиентом, не будет обрабатываться с «разрешения».

class Server:
    def __init__(self):
        #host = '192.168.0.2'
        host = '127.0.0.1'
        port = 50007
        addr = (host, port)
        self.UDPSock = socket(AF_INET, SOCK_DGRAM)
        self.UDPSock.bind(addr)
        self.UDPSock.settimeout(5.0)
        self.searchForClients = True
        self.playersOnline = []
        threading.Thread(target=self.permission).start()
        Gui.add_event("Server online on port %s" % port)


    def permission(self):
        global _status
        while self.searchForClients:
            time.sleep(0.5)
            _status.set("Status: Running; Connected: %s" % len(self.playersOnline))
            try:
                clientMessage, addr = self.UDPSock.recvfrom(1024) # , MSG_PEEK
            except:
                clientMessage = ""
            if clientMessage == "CONNECT" and addr not in self.playersOnline:                       
                if self.searchForClients:
                    self.addNewClient(addr)

            elif clientMessage == "DISCONNECT" and addr in self.playersOnline:
                self.removeClient(addr)

        Gui.add_event("No longer accepting logins")
        return False

    def clientRequests(self, addr):
        latestRequest = time.time()
        while addr in self.playersOnline:
            time.sleep(0.01)
            try:
                data, requestAddr = self.UDPSock.recvfrom(1024)
            except:
                requestAddr, data = "", ""
            if requestAddr == addr:
                latestRequest = time.time()
                dataCommand = data.split(':')
            if time.time() - latestRequest > 2:
                if addr in self.playersOnline:
                    self.removeClient(addr)

        if not self.searchForClients:       
            Gui.add_event("Player %s(%s) forcibly removed" % addr)
        return False

person KnasScripter    schedule 18.01.2012    source источник


Ответы (1)


Я считаю, что потоки излишне усложняют простые UDP-серверы, подобные этому. Просто слушайте сокет и отправляйте вызовы в зависимости от того, был ли уже виден исходный адрес пакета.

И нет, обычный системный вызов recvfrom(2) не позволяет вам «фильтровать», с какого адреса вы получаете данные, только для получения этой информации. Фильтрация выполняется с помощью connect(2) в UDP. сокет, но это ограничивает вас одним источником на сокет.

person Nikolai Fetissov    schedule 18.01.2012
comment
Ну, на самом деле это проект онлайн-игры, который я делаю с друзьями, и важно иметь один поток для каждого клиента, и этот поток для прослушивания только этого адреса :( PS То, что я там показал, явно не РЕДАКТИРОВАТЬ весь класс сервера: я поищу connect(2) спасибо.. - person KnasScripter; 18.01.2012
comment
Просто предложение — попробуйте подумать об игре с точки зрения конечного автомата. Вы можете обнаружить, что ваше предположение о необходимости наличия потоков неверно. - person Nikolai Fetissov; 18.01.2012