Есть ли способ ограничить количество подключений к указанному порту c на сервере протокола Twisted? - PullRequest
0 голосов
/ 03 мая 2020

У меня есть python витое серверное приложение, взаимодействующее с устаревшим клиентским приложением, и каждому клиенту был назначен определенный c порт для подключения к серверу. Поэтому я настроил прослушиватели на всех этих портах на сервере, и он прекрасно работает, но мне нужно встроить некоторые меры предосторожности, чтобы запретить подключение более одного клиента к одному и тому же порту сервера. В клиентском приложении слишком много вещей, которые ломаются, когда другой клиент подключен к тому же порту, и я не могу сейчас обновить это приложение. Я должен жить с тем, как это работает. Я знаю, что мог бы встроить некоторые функции logi c в функцию connectionMade (), чтобы посмотреть, существует ли уже кто-то на этом порту, и если это так, закрыть это новое соединение. Но я бы предпочел, чтобы был способ отклонить его с самого начала, поэтому клиенту даже не разрешено подключаться. Тогда клиент узнает, что он совершил ошибку, и он может изменить порт, к которому он пытается подключиться.

Вот сокращенная версия кода моего сервера, если это поможет.

from twisted.internet.protocol import Factory
from twisted.internet.protocol import Protocol
from twisted.internet import reactor
from twisted.internet import task
import time

class MyServerTasks():
    def someFunction(msg):
        #Do stuff

    def someOtherFunction(msg):
        #Do other stuff

class MyServer(Protocol):

    def __init__(self, users):
        self.users = users
        self.name = None

    def connectionMade(self):
        #Depending on which port is connected, go do stuff

    def connectionLost(self, reason):
        #Update dictionaries and other global info

    def dataReceived(self, line):
        t = time.strftime('%Y-%m-%d %H:%M:%S')
        d = self.transport.getHost()
        print("{} Received message from {}:{}...{}".format(t, d.host, d.port, line))  #debug
        self.handle_GOTDATA(line)

    def handle_GOTDATA(self, msg):
        #Parse the received data string and do stuff based on the message.
        #For example:
        if "99" in msg:
            MyServerTasks.someFunction(msg)

class MyServerFactory(Factory):

    def __init__(self):
        self.users = {} # maps user names to Chat instances

    def buildProtocol(self, *args, **kwargs):
        protocol = MyServer(self.users)
        protocol.factory = self
        protocol.factory.clients = []
        return protocol

reactor.listenTCP(50010, MyServerFactory())
reactor.listenTCP(50011, MyServerFactory())
reactor.listenTCP(50012, MyServerFactory())
reactor.listenTCP(50013, MyServerFactory())

reactor.run()

1 Ответ

0 голосов
/ 03 мая 2020

Когда клиент подключен к серверу, twisted использует factory для создания protocol (вызывая его buildProtocol метод) экземпляра для обработки клиентского запроса.

, поэтому вы можете сохранить счетчик подключенного клиента в вашем MyServerFactory, если счетчик достиг максимально допустимого подключенного клиента, вы можете вернуть None вместо создания нового протокола для этого клиента. Twisted закроет клиентское соединение, если фабрика не вернет протокол из метода buildProtocol.

, который вы можете увидеть здесь

class MyServer(Protocol):

def __init__(self, users):
    self.users = users
    self.name = None

def connectionMade(self):
    #Depending on which port is connected, go do stuff

def connectionLost(self, reason):
    #Update dictionaries and other global info
    self.factory.counter -= 1

def dataReceived(self, line):
    t = time.strftime('%Y-%m-%d %H:%M:%S')
    d = self.transport.getHost()
    print("{} Received message from {}:{}...{}".format(t, d.host, d.port, line))  #debug
    self.handle_GOTDATA(line)

def handle_GOTDATA(self, msg):
    #Parse the received data string and do stuff based on the message.
    #For example:
    if "99" in msg:
        MyServerTasks.someFunction(msg)



 class MyServerFactory(Factory):
   MAX_CLIENT = 2

 def __init__(self):
    self.users = {} # maps user names to Chat instances
    self.counter = 0

 def buildProtocol(self, *args, **kwargs):
    if self.counter == self.MAX_CLIENT:
        return None
    self.counter += 1
    protocol = MyServer(self.users)
    protocol.factory = self
    protocol.factory.clients = []
    return protocol
...