检测TCP何时拥塞python twisted socket服务器

时间:2015-06-03 06:52:14

标签: python tcp udp server twisted

我正在开发一款实时MMO游戏,并且有一个有效的TCP服务器(以及游戏客户端),但现在我考虑使用UDP 来不断更新其他玩家的位置(大大提高)从TCP拥塞控制中减少随机游戏填充!) 我喜欢这些东西比我更聪明的人的帮助(我是python / twisted的新手,在其他地方找不到这些信息;)

目前,我的服务器接受使用简单Twisted协议的连接。例如

global $brand_name = $row['brand_name'];

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 如何单独为每个协议实例实施拥塞检查?请在下面的代码示例中启动我的内容:(在这里说“请帮助!”) 我错误地想到了这个吗?任何指导都很棒,谢谢!

''' TCP reciever '''
class TCPProtocol(Protocol):

    def connectionMade(self):
        #add to list of connected clients
        factory.clients.append(self)

    def dataReceived(self, data):
        pass


#setup factory and TCP protocol class
factory = Factory()
factory.protocol = TCPProtocol
factory.clients = []
reactor.listenTCP(1959, factory)

1 个答案:

答案 0 :(得分:9)

You probably don't need UDP (yet)

你要说的第一件事是你想要减少来自TCP"的网络拥塞......这不是UDP的作用。 UDP允许您解决拥塞控制,实际上增加网络拥塞。在您了解如何实施自己的拥塞控制算法之前,高延迟连接上的UDP流量只会导致数据包风暴,从而使您的服务器不堪重负并淹没您的用户。网络连接,使它们无法使用。

在实时游戏中发送移动数据包的重要一点是,你总是希望确保不浪费时间和追赶"当新位置已经可用时,使用旧的移动包。在Twisted中,您可以使用producer and consumer APIs在TCP连接上执行此操作,就像这样:

from zope.interface import implementer
from twisted.internet.protocol import Protocol
from twisted.internet.interfaces import IPullProducer

def serializePosition(position):
    "... take a 'position', return some bytes ..."

@implementer(IPullProducer)
class MovementUpdater(Protocol, object):
    def updatePosition(self, newPosition):
        if newPosition != self.currentPosition:
            self.currentPosition = newPosition
            self.needToSendPosition()

    waitingToSend = False

    def needToSendPosition(self):
        if not self.waitingToSend:
            self.waitingToSend = True
            self.transport.registerProducer(self, False)

    def resumeProducing(self):
        self.transport.write(serializePosition(self.currentPosition))
        self.transport.unregisterProducer()
        self.waitingToSend = False

    def stopProducing(self):
        "nothing to do here"

每次游戏需要发送新位置时,都可以调用updatePosition来更新玩家的当前位置。 updatePosition首先更新当前位置,然后调用needToSendPosition,标记连接需要发送位置更新。这将协议注册为其传输的生成器,这将在每次写入缓冲区空间可用时调用resumeProducing。一旦resumeProducing被调用,我们就会发送最新位置的任何内容 - 如果在网络拥塞时调用updatePosition 500次,则只会立即发送一次更新随着拥堵的缓解。

这有点过于简单,因为每个transport一次只能有一个producer,而您的游戏服务器可能会有很多不同的位置更新发送给客户,因此您需要一个多路复用器,它聚合来自多个客户端的所有位置更新,还有一些代码来订购消息,这样除了位置更新之外的其他东西仍然可以通过,但位置更新具有优先权。

如果您仍然要进行UDP,这似乎是额外的工作,但如果您要正确地执行UDP并从中获得任何好处,您将需要实现非常类似的东西无论如何,所以这不会浪费。