示例#1
0
class TCP():
    def __init__(self, _core):
        print("TCP Protocol Startup...")
        self.core = _core
        self.config = self.core.server.config

    def start(self):
        self.setupTCP()
        self.startTCPTasks()

    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(
            self.config.TCPPORT, self.config.BACKLOG)
        self.tcpListener.addConnection(self.tcpSocket)
        print("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT)

    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler",
                    20)
        print("TCP Disconnection Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()

            if self.tcpListener.getNewConnection(rendezvous, netAddress,
                                                 newConnection):
                newConnection = newConnection.p()

                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                # Handle the connection depending on persistent or not
                if self.core.server.isPersistent:
                    self.core.handleConnection(generateUUID(), newConnection,
                                               netAddress)
                else:
                    self.core.createPlayerObject(generateUUID(), newConnection,
                                                 netAddress)

                print("Server: New Connection from -",
                      str(netAddress.getIpString()))
            else:
                print("Server: Connection Failed from -",
                      str(netAddress.getIpString()))

        return Task.cont

    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                self.core.packetManager.handlePacket(opcode, data,
                                                     datagram.getAddress())

        return Task.cont

    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)

    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)

            for client in self.core.server.clients:
                if self.core.server.clients[
                        client].connection == resetConnection.p():
                    del self.core.server.clients[client]
                    self.tcpReader.removeConnection(resetConnection.p())
                    print("Removed Connection:", resetConnection.p())
                    print('Current Clients:', self.core.server.clients)
                    break

        return Task.cont

    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)

    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)
示例#2
0
文件: TCP.py 项目: grimfang/grim_net
class TCP():

    def __init__(self, _core):
        print ("TCP Protocol Startup...")
        self.core = _core
        self.config = self.core.server.config


    def start(self):
        self.setupTCP()
        self.startTCPTasks()


    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.config.TCPPORT, self.config.BACKLOG)
        self.tcpListener.addConnection(self.tcpSocket)
        print ("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT)


    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print ("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print ("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20)
        print ("TCP Disconnection Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            
            if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection):
                newConnection = newConnection.p()
                
                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                # Handle the connection depending on persistent or not
                if self.core.server.isPersistent:
                    self.core.handleConnection(generateUUID(), newConnection, netAddress)
                else:
                    self.core.createPlayerObject(generateUUID(),newConnection, netAddress)
                    
                print ("Server: New Connection from -", str(netAddress.getIpString()))
            else:
                print ("Server: Connection Failed from -", str(netAddress.getIpString()))    
                    
            
        return Task.cont


    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                self.core.packetManager.handlePacket(opcode, data, datagram.getAddress())
                
        return Task.cont


    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)


    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)
            
            for client in self.core.server.clients:
                if self.core.server.clients[client].connection == resetConnection.p():
                    del self.core.server.clients[client]
                    self.tcpReader.removeConnection(resetConnection.p())
                    print ("Removed Connection:", resetConnection.p())
                    print ('Current Clients:', self.core.server.clients)
                    break

        return Task.cont


    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)


    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)
示例#3
0
class Server:
    def __init__(self):

        self.port = 5555
        self.addr = "127.0.0.1"
        self.backlog = 7
        self.active_connections = dict()
        self.start = False

        self.connect()

    def connect(self) -> None:
        # Handle connections and terminations
        self.manager = QueuedConnectionManager()
        # Wait for clients connection requests
        self.listener = QueuedConnectionListener(self.manager, 0)
        # Buffers incoming data from active connection
        self.reader = QueuedConnectionReader(self.manager, 0)
        # Transmit PyDatagrams to active connection
        self.writer = ConnectionWriter(self.manager, 0)
        # Open TCP Rendezvous to accept client connections with a limit
        self.socket = self.manager.openTCPServerRendezvous(
            self.port, self.backlog)
        self.listener.addConnection(self.socket)
        print("Server listening on port %s...." % str(self.port))
        # Listen for mew incoming connections
        taskMgr.add(self.handle_incoming_connections,
                    "Poll the connection listener", -39)
        # Listen for new datagrams
        taskMgr.add(self.handle_connection_data,
                    "Poll the connection reader", -40)
        # Listen for dropped connections
        taskMgr.add(self.handle_dropped_connections,
                    "Poll the dropped connection listener", -41)
        # See if game can be started
        taskMgr.add(self.start_game, "Start Game", -42)

    def start_game(self, task_data: Task) -> Task:
        if len(self.active_connections) == self.backlog:
            self.start = True
        return Task.cont

    def handle_incoming_connections(self, task_data: Task) -> Task:
        if self.listener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            net_addr = NetAddress()
            new_connection = PointerToConnection()
            if self.listener.getNewConnection(rendezvous, net_addr, new_connection):
                new_connection = new_connection.p()
                # Keep track of our active connections
                self.active_connections[str(
                    new_connection.this)] = new_connection
                # Start reading the new connection
                self.reader.addConnection(new_connection)
                print("%s just connected" % str(new_connection))
        return Task.cont

    def handle_connection_data(self, task_data: Task) -> Task:
        if self.reader.dataAvailable():
            # Catch the incoming data
            datagram = NetDatagram()
            if self.reader.getData(datagram):
                name = self.handle_client_message(datagram)
                broadcast = f"Everyone, welcome {name} to the game!"
                self.broadcast_message(broadcast)

        return Task.cont

    def handle_dropped_connections(self, task_data: Task) -> Task:
        if self.manager.resetConnectionAvailable():
            connection_pointer = PointerToConnection()
            self.manager.getResetConnection(connection_pointer)
            lost_connection = connection_pointer.p()
            print("% s disconnected from server" % str(lost_connection))
            del self.active_connections[str(lost_connection.this)]
            self.manager.closeConnection(lost_connection)
        return Task.cont

    def handle_client_message(self, message: str) -> str:
        iterator = PyDatagramIterator(message)
        return iterator.getString()

    def get_connections_count(self) -> int:
        return len(self.active_connections)

    def send_personal_message(self, message: str, client: PointerToConnection) -> None:
        datagram = self.create_new_datagram(message)
        self.writer.send(datagram, client)

    def broadcast_message(self, message: str) -> None:
        datagram = self.create_new_datagram(message)
        for client in self.active_connections:
            self.writer.send(datagram, self.active_connections[client])

    def create_new_datagram(self, message: str) -> PyDatagram:
        new_datagram = PyDatagram()
        new_datagram.addString(message)
        return new_datagram

    def terminate_all_clients(self) -> None:
        for client in self.active_connections:
            self.reader.removeConnection(client)
        self.active_connections = list()

    def terminate_specific_client(self, client: PointerToConnection) -> None:
        self.reader.removeConnection(client)
        del self.active_connections[str(client)]
示例#4
0
class Client(DirectObject):
    def __init__(self,
                 host,
                 port,
                 timeout=3000,
                 compress=False,
                 connectionStateChangedHandler=None):
        DirectObject.__init__(self)

        self.connectionStateChangedHandler = connectionStateChangedHandler

        self.myConnection = None

        self.host = host
        self.port = port
        self.timeout = timeout
        self.compress = compress

        self.cManager = QueuedConnectionManager()
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager, 0)

        # By default, we are not connected
        self.connected = False

        self.passedData = []

        self.connect(self.host, self.port, self.timeout)

    def cleanup(self):
        self.removeAllTasks()

    def startPolling(self):
        self.doMethodLater(0.1, self.tskDisconnectPolling,
                           "clientDisconnectTask")

    def connect(self, host, port, timeout=3000):
        # Connect to our host's socket
        self.myConnection = self.cManager.openTCPClientConnection(
            host, port, timeout)
        if self.myConnection:
            self.myConnection.setNoDelay(True)
            self.myConnection.setKeepAlive(True)
            print "Connected"
            self.cReader.addConnection(
                self.myConnection)  # receive messages from server
            self.connected = True  # Let us know that we're connected
            self.startPolling()
            if self.connectionStateChangedHandler:
                self.connectionStateChangedHandler.handleConnection()
        else:
            print "Unable to connect"
            if self.connectionStateChangedHandler:
                self.connectionStateChangedHandler.handleFailure()

    def tskDisconnectPolling(self, task):
        if not self.connected:
            return Task.done

        # TODO: Hacky sending nothing to force disconnect triggers
        #self.sendData()
        # Also checking for dataAvailable on reader will trigger the connection disconnected
        self.cReader.dataAvailable()
        # TODO: Confirm this works for client side (to both game server and master server)
        while self.cManager.resetConnectionAvailable():
            connPointer = PointerToConnection()
            self.cManager.getResetConnection(connPointer)
            connection = connPointer.p()

            # Remove the connection we just found to be "reset" or "disconnected"
            self.cReader.removeConnection(connection)

            # Let us know that we are not connected
            self.connected = False
            print "disconnected"

            if self.connectionStateChangedHandler:
                self.connectionStateChangedHandler.handleDisconnection()

        return Task.again

    def processData(self, netDatagram):
        myIterator = PyDatagramIterator(netDatagram)
        return self.decode(myIterator.getString())

    def encode(self, data, compress=False):
        # encode(and possibly compress) the data with rencode
        return rencode.dumps(data, compress)

    def decode(self, data):
        # decode(and possibly decompress) the data with rencode
        return rencode.loads(data)

    def sendData(self, data=None):
        myPyDatagram = PyDatagram()
        myPyDatagram.addString(self.encode(data, self.compress))
        self.cWriter.send(myPyDatagram, self.myConnection)

    def passData(self, data):
        self.passedData.append(data)

    def getData(self):
        data = self.passedData
        self.passedData = []
        while self.cReader.dataAvailable():
            datagram = NetDatagram()
            if self.cReader.getData(datagram):
                data.append(self.processData(datagram))
        return data
示例#5
0
class Server(DirectObject):
    # TODO: Perhaps a better way to do this?
    handleNewConnection = None
    handleLostConnection = None

    def __init__(self, port, backlog=1000, compress=False):
        DirectObject.__init__(self)

        self.port = port
        self.compress = compress

        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager, 0)

        self.passedData = []

        self.connect(port, backlog)
        self.startPolling()

    def connect(self, port, backlog):
        # Bind to our socket
        tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
        self.cListener.addConnection(tcpSocket)

    def startPolling(self):
        self.addTask(self.tskListenerPolling, "serverListenTask", -40)
        self.addTask(self.tskDisconnectPolling, "serverDisconnectTask", -39)

    def tskListenerPolling(self, task):
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()

            if self.cListener.getNewConnection(rendezvous, netAddress,
                                               newConnection):
                newConnection = newConnection.p()
                newConnection.setNoDelay(True)
                newConnection.setKeepAlive(True)
                if self.handleNewConnection:
                    self.handleNewConnection(newConnection)
                self.cReader.addConnection(
                    newConnection)  # Begin reading connection
        return Task.cont

    def tskDisconnectPolling(self, task):
        while self.cManager.resetConnectionAvailable():
            connPointer = PointerToConnection()
            self.cManager.getResetConnection(connPointer)
            connection = connPointer.p()

            # Remove the connection we just found to be "reset" or "disconnected"
            self.cReader.removeConnection(connection)

            if self.handleLostConnection:
                self.handleLostConnection(connection)

        return Task.cont

    def processData(self, netDatagram):
        myIterator = PyDatagramIterator(netDatagram)
        return self.decode(myIterator.getString())

    def encode(self, data, compress=False):
        # encode(and possibly compress) the data with rencode
        return rencode.dumps(data, compress)

    def decode(self, data):
        # decode(and possibly decompress) the data with rencode
        return rencode.loads(data)

    def sendData(self, data, con):
        myPyDatagram = PyDatagram()
        myPyDatagram.addString(self.encode(data, self.compress))
        self.cWriter.send(myPyDatagram, con)

    def passData(self, data, connection):
        self.passedData.append((data, connection))

    def getData(self):
        data = self.passedData
        self.passedData = []
        while self.cReader.dataAvailable():
            datagram = NetDatagram()
            if self.cReader.getData(datagram):
                data.append(
                    (datagram.getConnection(), self.processData(datagram)))
        return data
示例#6
0
class SocketTCP(ShowBase):

    def __init__(self, _parent=None):
        ShowBase.__init__(self, windowType = 'none')
        print ("TCP Protocol Startup...")
        #self.parent = _parent

        #self.config = self.parent.server.config
        # tmp config
        self.tcpport = 6000
        self.backlog = 10
        self.hostname = '127.0.0.1'

        self.sendPacketQueue = None


    def startAll(self):
        self.setupTCP()
        self.startTCPTasks()


    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.tcpport, self.backlog)
        self.tcpListener.addConnection(self.tcpSocket)
        print ("Started Server on: ", self.hostname, self.tcpport)


    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print ("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print ("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20)
        print ("TCP Disconnection Handler Started")
        taskMgr.add(self.tcpQueuedSendHandlerTask, "tcpQueuedSendhandlerTask", -11)
        print ("TCP Queued Send Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            
            if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection):
                newConnection = newConnection.p()
                
                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                #self.core.createPlayerObject(generateUUID(),newConnection, netAddress)
                    
                print ("Server: " + str(generateUUID), str(netAddress.getIpString()))
            else:
                print ("Server: Connection Failed from -", str(netAddress.getIpString()))    
                    
            
        return Task.cont


    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                #self.core.packetManager.handlePacket(opcode, data, datagram.getAddress())
                print("Set Packet Handler to handle packets!")
                
        return Task.cont


    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)


    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)
            print(str(resetConnection.p()))
            #for client in self.core.server.clients:
            #    if self.core.server.clients[client].connection == resetConnection.p():
            #        del self.core.server.clients[client]
            #        self.tcpReader.removeConnection(resetConnection.p())
            #        print ("Removed Connection:", resetConnection.p())
            #        print ('Current Clients:', self.core.server.clients)
            #        break

        return Task.cont


    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)


    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)

    def addPacketToSendQueue(self, _data):
        # _data should contain packet and connection
        pass

    def addPacketToBroadcastQueue(self, _pkt, _connectionList):
        # _data should contain the pkt data and _connectionList should be the valid connections for that broadcast
        # Could have a grouping system that put clients together and broadcasts go per group
        pass

    def tcpQueuedSendHandlerTask(self, task):
        
        if not self.sendPacketQueue.isEmpty():
            self.addPacketToSendQueue(self.sendPacketQueue.removeFromQue())
        
        return Task.cont