That essentially creates an associative array of ID => connection for everybody connected to my server (I use the connection ID for a bunch of things).
So now I want to send out a datagram to everybody that is connected:
myAnnouncement = PyDatagram()
myAnnouncement.addString("HEEEYYYY YOU GUYYYYYYSSSS!")
for connectionID, connection in self.Connections():
self.cWriter.send(myAnnouncement, connection)
Is there a more efficient way of doing this? I.e. is there any way to supply a list of connections to the send function directly? Or is this about as efficient as it will get? I did look through the documentation and see no way of putting a list/array as one of the arguments for the send function, but I want to make sure I didn’t overlook something.
My biggest concern is lag/server load. If I have 50 connections, that’s 50 packets I’m sending out for something really simple. It may not be much, but it adds up if you are doing this every second.
Bonus points if you can identify where that announcement comes from
Is that the most efficient method? Or is the some other way that might run faster?
My concern here is that supposed my datagram is 25 bytes. At 50 connections that consumes 1.25k bytes. Yeah that ain’t much (thankfully).
However at 5000 connections (yeah I know, the chances of my getting a game running with 5000 concurrent connections running is slim to none), that’s 102.5k bytes.
Now that I think of it, that’s actually not that bad if sending it out once/second. My home computer could probably handle that.
I was hoping there would be a way to address a packet to multiple connections, so instead of sending 50 identical packets, you could send 1 packet that would go to 50 clients.
It doesn’t actually send the messages one at a time, even though it looks like that’s what you’re asking it to do. They get queued up and sent out to the different sockets in parallel by the operating system. So this is still pretty efficient.
Now, if you really wanted to do it super-efficiently, you’d use non-blocking I/O and code it all in C++. That’s the only way to scale up to super big. In Python, though, you ought to be able to handle at least a few hundred connections before you start to suffer.
def StartConnectionManager(self):
# this function creates a connection manager, and then
# creates a bunch of tasks to handle connections
# that connect to the server
self.cManager = QueuedConnectionManager()
self.cListener = QueuedConnectionListener(self.cManager, 0)
self.cReader = QueuedConnectionReader(self.cManager, 0)
self.cWriter = ConnectionWriter(self.cManager,0)
self.tcpSocket = self.cManager.openTCPServerRendezvous(self.port,self.backlog)
self.cListener.addConnection(self.tcpSocket)
self.portStatus = "Open"
taskMgr.add(self.ConnectionManagerTASK_Listen_For_Connections,"Listening for Connections",-39)
# This task listens for new connections
taskMgr.add(self.ConnectionManagerTASK_Listen_For_Datagrams,"Listening for Datagrams",-40)
# This task listens for new datagrams
taskMgr.add(self.ConnectionManagerTASK_Check_For_Dropped_Connections,"Listening for Disconnections",-41)
# This task listens for disconnections
def ConnectionManagerTASK_Listen_For_Connections(self, task):
if(self.portStatus == "Open"):
# This exists in case you want to add a feature to disable your
# login server for some reason. You can just put code in somewhere
# to set portStatus = 'closed' and your server will not
# accept any new connections
if self.cListener.newConnectionAvailable():
print "CONNECTION"
rendezvous = PointerToConnection()
netAddress = NetAddress()
newConnection = PointerToConnection()
if self.cListener.getNewConnection(rendezvous,netAddress,newConnection):
newConnection = newConnection.p()
self.Connections[str(newConnection.this)] = rendezvous
# all connections are stored in the self.Connections
# dictionary, which you can use as a way to assign
# unique identifiers to each connection, making
# it easy to send messages out
self.cReader.addConnection(newConnection)
myResponse = PyDatagram()
sendCommand = self.CommandMatrix.MatrixVar("DECLARE_CONNECTION_ID")
myResponse.addUint8(sendCommand)
myResponse.addUint32(newConnection.this)
self.cWriter.send(myResponse, newConnection)
print "\n---------------\nSOMEBODY CONNECTED"
print "IP Address: " + str(newConnection.getAddress())
print "Connection ID: " + str(newConnection.this)
print "---------------"
# you can delete this, I've left it in for debugging
# purposes
return Task.cont