My network code for my client is in a threaded (using panda’s threading) class. When the application launches the thread the main game engine seems to pause. messenger.toggleVerbose() only progresses when information is received or sent. Here is the link to my netcode. Any ideas or suggestions?
Ah, you are using Python sockets, which blocks the whole process, because it doesn’t know about Panda threads. Note that in Panda’s default compilation mode, “threads” are not true threads at all, but are simulated within the Panda code, which provides a lower overhead overall.
You should either put the sockets into non-blocking I/O (and use polling rather than blocking, with a call to Thread.considerYield() in the loop), or switch to using Panda sockets instead (which does this for you), or recompile Panda yourself to use true threads.
David
No, you have to go a little higher than that. You would be using Connection, ConnectionManager, ConnectionWriter, ConnectionReader, and so on.
These classes are briefly described in the Panda3D manual under Networking. I believe there are many examples in the forum as well.
David
I use asyncore (it uses socket too), and its loop() is also blocking.
I worked around it by calling it every frame in a task, but using 0 timeout and 1 poll count.
Works perfectly and still simple.
I am trying to use panda’s connections still using google protocol buffers as the medium. I set the reader and writer to raw. I can send strings just fine, however receiving raw strings is still an issue. ConnectionReader.dataAvailiable() returns true, but getData just returns an empty string.
# -*- coding: utf-8 -*-
"""
Network stuffs
"""
import protocol_pb2 as proto
from direct.showbase import DirectObject
from direct.stdpy import threading
from pandac.PandaModules import QueuedConnectionManager, QueuedConnectionReader, ConnectionWriter, QueuedConnectionListener
# Networking
import socket
class ServerSocket(threading.Thread, DirectObject.DirectObject):
"""
Connection to client
"""
def __init__(self):
"""
Overide to threading for client socket
self.buffer: Buffer string for incoming messages
"""
self.cManager = QueuedConnectionManager()
self.cReader = QueuedConnectionReader(self.cManager,0)
self.cReader.setRawMode(True)
self.cWriter = ConnectionWriter(self.cManager,0)
self.cWriter.setRawMode(True)
self.cListener = QueuedConnectionListener(self.cManager, 0)
self.connection = None
self.buffer = ""
self.accept("exit", self.exit)
self.accept("connect", self.connect)
self.accept("sendData", self.send)
threading.Thread.__init__(self)
def connect(self, host, userName, userPassword):
"""
connects with the server
"""
# Fire login data!
self.myConnection= self.cManager.openTCPClientConnection(host,52003,3000)
self.cReader.addConnection(self.myConnection)
container = proto.Container()
container.login.name = userName
container.login.password = userPassword
container.login.regionPassword = ""
self.send(container)
self.start()
def run(self):
self.running = True
import time
while self.running:
d = ""
print "Data?", self.cReader.dataAvailable()
time.sleep(1)
if self.cReader.dataAvailable():
v = self.cReader.getData(d)
print "I gots:", v, d
self.buffer += d
# We now check for the end tag "[!]" and fire off the appropriate serialized string
if "[!]" in self.buffer:
# Only one string is brought out at a time
# What ever partial or complete message is left is put back into the buffer for the next cycle
# This is because I am lazy
data, self.buffer = self.buffer.split("[!]", 1)
self.processData(data)
def processData(self, data):
"""
Processes network communication into engine events
Some responses do not need any additional processing
so we respond right away
"""
# Stuff goes here
def send(self, data):
"""
sends data to client
data needs to be a Protocol Buffer Container object
"""
try:
print "Sending Data:", str(data)[0:100]
self.cWriter.send(data.SerializeToString(),self.myConnection)
except:
raise
print "Object is not a protocol buffer object or is missing a parameter."
def exit(self):
self.s.close()
self.running = False
self.client.setblocking(0) wont work?
Hmm, I’m not sure how well the threaded read mechanism works in raw mode. I’ll have to investigate.
David
I switched to polling, however considerYield does not exist in threading.Thread (is “from direct.stdpy import threading” correct?). Is this not in 1.6.2 or am I totally missing something?
No, sorry, this is PandaModules.Thread, a different class. The Thread class in stdpy.threading is designed to emulate Python’s Thread class, which doesn’t have that interface. But it’s probably not a bad idea to add it, for convenience. I’ll do that for 1.7.0. In the meantime, just use PandaModules.Thread.considerYield instead.
David