I was wondering what could be wrong with the following code, that is trying to send a pyDatagram to all connected clients.
If i run this code, i get an error on the cWriter.send part.
AssertionError:!_shutdown at line 167 of c:\buildslave\release_sdk_win32\build\panda3d\panda\src\net\connectionWriter.cxx
# broadcast a message to all clients
def myNewPyDatagram(self):
# Send a test message
myPyDatagram = PyDatagram()
myPyDatagram.addUint8(PRINT_MESSAGE)
myPyDatagram.addString("Hello, world!")
return myPyDatagram
def tskBBC(taskdata):
for aClient in activeConnections:
TestDatagram = myNewPyDatagram(self)
cWriter.send(TestDatagram,aClient)
return Task.cont
It’s telling you that your ConnectionWriter has already destructed or been otherwise cleaned up. Something is therefore broken in the way you are creating and storing your ConnectionWriter.
This can also happen if you allow your ConnectionManager to destruct, which automatically invalidates any objects it is managing.
import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.PyDatagramIterator import PyDatagramIterator
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.showbase.DirectObject import DirectObject
from direct.gui.OnscreenText import OnscreenText
class World(DirectObject):
#Macro-like function used to reduce the amount to code needed to create the
#on screen instructions
def genLabelText(self, text, i):
return OnscreenText(text = text, pos = (-1.3, .95-.05*i), fg=(1,1,1,1),
align = TextNode.ALeft, scale = .05)
activeConnections=[] # We'll want to keep track of these later
def __init__(self):
#This code puts the standard title and instruction text on screen
self.title = OnscreenText(text="Panda3D: NCS Server window",
style=1, fg=(0,0,0,1),
pos=(0.8,-0.95), scale = .07)
cManager = QueuedConnectionManager()
cListener = QueuedConnectionListener(cManager, 0)
cReader = QueuedConnectionReader(cManager, 0)
cWriter = ConnectionWriter(cManager,0)
activeConnections=[] # We'll want to keep track of these later
port_address=9099 #No-other TCP/IP services are using this port
backlog=1000 #If we ignore 1,000 connection attempts, something is wrong!
tcpSocket = cManager.openTCPServerRendezvous(port_address,backlog)
cListener.addConnection(tcpSocket)
PRINT_MESSAGE = 1
self.j = 0
# broadcast a message to all clients
def myNewPyDatagram(self):
# Send a test message
myPyDatagram = PyDatagram()
myPyDatagram.addUint8(PRINT_MESSAGE)
myPyDatagram.addString("Hello, world!")
return myPyDatagram
def tskBBC(taskdata):
for aClient in activeConnections:
TestDatagram = myNewPyDatagram(self)
cWriter.send(TestDatagram,aClient)
return Task.cont
def tskReaderPolling(taskdata):
if cReader.dataAvailable():
datagram=NetDatagram() # catch the incoming data in this instance
# Check the return value; if we were threaded, someone else could have
# snagged this data before we did
if cReader.getData(datagram):
myProcessDataFunction(datagram)
return Task.cont
def tskListenerPolling(taskdata):
if cListener.newConnectionAvailable():
rendezvous = PointerToConnection()
netAddress = NetAddress()
newConnection = PointerToConnection()
if cListener.getNewConnection(rendezvous,netAddress,newConnection):
newConnection = newConnection.p()
activeConnections.append(newConnection) # Remember connection
cReader.addConnection(newConnection) # Begin reading connection
self.genLabelText(format(len(activeConnections)),len(activeConnections))
return Task.cont
taskMgr.add(tskListenerPolling,"Poll the connection listener",-39)
taskMgr.add(tskReaderPolling,"Poll the connection reader",-40)
taskMgr.add(tskBBC,"Broadcasting")
w=World()
run()
this is the entire code, can’t think where the writer would be destroyed or cleared. I’m new to panda though, so maybe i’ve missed something. Any advice?
These lines simply define local variables that automatically destruct as soon as the init() function returns. Since it appears that you intend for these variables to persist for the lifetime of your class object, you should store them in the class instead like this: