Multiple responses in Twisted

冷暖自知 提交于 2020-01-24 15:54:05

问题


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

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)
    ...  

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?

EDIT:

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)

回答1:


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

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.

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.

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.



来源:https://stackoverflow.com/questions/14588131/multiple-responses-in-twisted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!