【问题标题】:Is there a way to restrict number of connections to a specific port in a Twisted protocol server?有没有办法限制到 Twisted 协议服务器中特定端口的连接数?
【发布时间】:2020-05-02 22:42:56
【问题描述】:

我有一个 python Twisted 服务器应用程序与旧客户端应用程序接口,并且每个客户端都被分配了一个特定的端口来连接到服务器。所以我已经在服务器上的所有这些端口上设置了监听器,它工作得很好,但是我需要建立一些保护措施来禁止多个客户端连接到同一个服务器端口上。当另一个客户端连接到同一个端口时,客户端应用程序上有太多东西会中断,我现在无法更新该应用程序。我必须忍受它的运作方式。 我知道我可以在 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()

【问题讨论】:

    标签: python twisted twisted.internet


    【解决方案1】:

    当客户端连接到服务器时,twisted使用factory创建 一个protocol(通过调用它的buildProtocol方法)实例来处理客户端请求。

    因此,您可以在MyServerFactory 中维护已连接客户端的计数器, 如果计数器已达到最大允许连接的客户端,您可以返回 None 而不是为该客户端创建新协议。 如果工厂没有返回协议,Twisted 将关闭客户端连接 它的buildProtocol 方法。

    you can see here

    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
    

    【讨论】:

    • 如果我理解正确,这应该计算所有客户端连接并将服务器连接限制为 1。这越来越接近,但我希望此服务器上有多个客户端,只是每个客户端都应该专用于一个端口。
    • 但只是为了好玩,我按照您的建议修改了我的代码,它仍然允许多个客户端从任何端口连接。我认为这与 self.counter 在工厂内部而不是全局有关,所以每次用户连接时它都会重置为 0?
    • 在这种情况下,您可以更改 MAX_CLIENT 的值以仅允许 MAX_CLIENT 连接到服务器,例如。如果您只想允许一个客户端,请将其更改为 1。工厂只实例化了一次,(你实例化它并将它作为参数提供给reactor.listenTCP)。所以这里没有重置发生。当客户端连接扭曲调用时,工厂的(你给 reactor.listenTCP 作为参数的那个)buildProtocol 方法没有实例化一个新工厂并且调用它的 buildProtocol 方法。
    • 啊哈!谢谢你的澄清。我误读了逻辑,无法弄清楚为什么它不起作用。我用 MAX_CLIENT = 1 进行了更新,它起作用了。现在唯一的问题是我需要以某种方式构建以在连接关闭时重置该计数器,因为一旦客户端从该端口关闭,就不允许任何人再次连接到它!也许是一个全局变量或计数器字典?
    • 不使用全局变量的最简单方法是在 protocol.connectionLost 方法中将 factory.counter 的值减 1 factory.counter -= 1。我已经更新了答案中的代码以反映这一点。
    猜你喜欢
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    相关资源
    最近更新 更多