Twisted 中的多重响应 [英] Multiple responses in Twisted

查看:76
本文介绍了Twisted 中的多重响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Twisted 和 Pygame 开发简单的 TCP clinet/服务器游戏,但是我在向客户端发送数据时遇到了困难.Twisted 不允许我连续发送多个响应.这就是我想要做的:

I'm trying to develop simple TCP, clinet/server game using Twisted and Pygame, but I have difficulties with sending data to clients. Twisted doesn't allow me to send multiple responses in a row. That's what I'm trying to do:

我有处理玩家状态变化并将它们重新发送给其他客户端的方法:

I have method witch handle player status changes and resend them to other clients:

def handle_stateChanged(self, data):
    #get playerState from client and override local copy of player
    #check if all players are ready
    #if needed, change gameState form 'inLOBBY' to 'inGAME'
    #if gameState == 'inGAME', start 'proceed' method (see below)
    #send message about player and game state to others

proceed 方法(使用 LoopingCall 每 1s/30 调用一次),只需计算所有游戏内容并将其发送给玩家.这两个函数相互阻塞,分别工作得很好,但是当一起工作时,只有来自其中之一的数据才能到达目的地.类似的东西也不起作用:

and proceed method(called every 1s/30 using LoopingCall) with simply calculate all game stuff and send it to players. Those two functions block each other, separately they work just fine, but when working together only data from one of them reach destination. Also something like this doesn't work:

def dataRecived(self, data):
    ...
    sendData(data1) #only data1 is delivered
    sendData(data2)
    ...  

我不知道这是 TCP 的工作方式,还是我对 Twisted 缺乏了解.我应该如何向客户端发送更新并在后台处理用户输入?

I don't know if it's the way TCP works or it's my lack of knowledge on Twisted. How should I send updates to clients and in background handle user input?

class Server(Protocol):
    def __init__(self, factory):
        self.factory = factory
        self.player = None #when connection is made here goes my player class
        self.world = factory.world
        ...
        self.factory.loop = LoopingCall(self.proceed)

    def dataReceived(self, data):
        data = pickle.loads(data)
        #this calls 'handle_stateChanged'
        getattr(self, 'handle_{}'.format(data['header']))(data) #data[header] = 'stateChanged'

    def handle_stateChanged(self, data):      
        isReady = data['isReady']
        self.player.isReady = isReady

        if isReady:
            count = 0
            for connection in self.factory.connections.values():
                if connection.player.isReady:
                    count += 1

            if count == len(self.factory.connections) and count > 1 and self.world.state == 'inLOBBY':
                self.world.state = 'inGAME'
                self.world.playersDistribution(self.factory.connections)
                self.factory.loop.start(1 / 30)

        data['state'] = self.world.state
        data['players'] = self.getPlayers()        
        self.sendToOthers(data)

    def sendToOthers(self, data, omitId = None):
        connections = self.factory.connections

        for key in connections.keys():
            if key != omitId:
                connections[key].sendData(data)

    def proceed(self):
        #It's only a prototype of my method. 
        #The point is that the client keep getting
        #'test' and data from self.sendToOthers(data) in handle_stateChanged
        #is not being delivered even if the method (handle_stateChanged) is called

        if self.world.state != 'inGAME':
            return

        data = {'header' : 'message', 'body' : 'test'}
        #When i comment this out, handle_stateChanged works fine and sends data
        self.sendToOthers(data)

class ServerFactory(Factory):

    def __init__(self, world):
        self.world = world
        self.connections = {}

    def buildProtocol(self, addr):
        return Server(self)

推荐答案

您的服务器中存在远程任意代码执行漏洞.

Your server has a remote arbitrary code execution vulnerability in it.

在极少数情况下(如果有的话)您应该对从网络接收到的数据进行解压缩.这样做允许任何对等方出于任意的、可能是恶意的目的劫持您的服务器.注意pickle 文档中的大红框.

There are very few - if any - circumstances under which you should unpickle data received from the network. Doing so allows any peer to hijack your server for arbitrary, perhaps malicious, purposes. Note the big red box in the pickle documentation.

除了这个严重的安全问题之外,您遇到的问题是,只有第一条被发送的数据被解释,这可能是由于这两条数据在穿越网络时被连接在一起造成的.您的接收代码没有适当的帧支持,因此无法判断有两条消息.碰巧的是,pickle 会从第一条消息加载数据,然后忽略代表第二条消息的额外数据,从而有效地将这些数据丢弃在地板上.

Apart from this serious security issue, the problem you're having with only the first piece of data being sent being interpreted is probably caused by the two pieces of data being joined together as they traverse the network. Your receiving code has no proper framing support, so it can't tell there are two messages. It so happens that pickle will load data from the first message and ignore the extra data afterwards which represents the second message, effectively dropping that data on the floor.

如果您切换到更具表现力的协议(比传输无帧泡菜字符串的裸 TCP 更具表现力),例如 AMP.

Both the security problem and the framing problem can be solved if you switch to a more expressive protocol (more expressive than bare TCP transporting unframed pickle strings), for example AMP.

这篇关于Twisted 中的多重响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆