silentpolygon
28-12-2007 08:50:27
Has anyone ever done networkprogramming with plib?
Just want to get one foot into it.
Just want to get one foot into it.
silentpolygon
28-12-2007 08:50:27
jaaku1111
28-01-2008 01:13:40
import socket
import threading
import select
import sys
import struct
class pyNetServer:
"Simple-to-use Network Server"
def __init__(self):
self.HOST = socket.gethostname()
#self.HOST = 'localhost'
self.BUFSIZ = 1024
self.BACKLOG = 2
self.ssocket = None
self.threads = []
self.listener = None
self.lock = threading.Lock()
self.Running = 1
def Start(self,port):
try:
print 'Starting Server At Host: ' + str(self.HOST) + ' on Port: ' + str(port)
self.ADDR = (self.HOST,port)
self.ssock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.ssock.bind(self.ADDR)
self.ssock.listen(self.BACKLOG)
except socket.error, (value, message):
if self.ssocket:
self.ssocket.close()
print "Couldn't open socket: " + message
sys.exit(1)
#now kick off the listener thread (run)
self.listener = pyNetServerListener(self)
self.listener.start()
def Close(self):
self.Running = 0
#self.lock.acquire()
for t in self.threads:
t.Close()
#self.lock.release()
self.listener.running = 0
self.ssock.close()
def SendAll(self, msg):
self.lock.acquire()
for t in self.threads:
t.Send(msg)
self.lock.release()
def GetMessages(self):
msgs = []
clients_to_remove = []
try:
#self.lock.acquire()
for c in self.threads:
o = c.GetMessage()
while o != None:
client_closed = False
if isinstance(o,str):
if o == 'client closed!@#$%':
#client closed, so kill their thread.
#print 'client closed!'
client_closed = True
clients_to_remove.append(c)
msgs.append( (c,'-disconnected-') )
if not client_closed:
msgs.append( (c,o) )
o = c.GetMessage()
finally:
pass#self.lock.release()
while len(clients_to_remove) > 0:
c = clients_to_remove.pop(0)
c.Close()
return msgs
class pyNetServerListener(threading.Thread):
def __init__(self,parent):
threading.Thread.__init__(self)
self.Parent = parent
self.running = 1
def run(self):
while self.running:
inputready,outputready,exceptready = select.select([self.Parent.ssock],[],[],2)
for s in inputready:
if s == self.Parent.ssock:
try:
client, address = self.Parent.ssock.accept()
sc = pyNetServerClient((client,address),self.Parent)
sc.start()
self.Parent.lock.acquire()
self.Parent.threads.append(sc)
self.Parent.lock.release()
except socket.error, (value,message):
pass#print 'got a socket error in the server listener ' + message
else:
print 'NON Parent.ssock event!!!'
class pyNetServerClient(threading.Thread):
def __init__(self,(csocket,address),parent):
threading.Thread.__init__(self)
self.Parent = parent
self.csocket = csocket
self.address = address
self.BUFSIZ = 1024
self.running = True
self.msgqueue = []
self.lock = threading.Lock()
def run(self):
while self.running:
try:
inputready,outputready,exceptready = select.select([self.csocket],[],[],2)
for s in inputready:
if s == self.csocket:
finished = 0
remaining = ""
while not finished:
finished = 1 # preset to finished, is reset if theres remaining data
total_len=0;total_data=[];size=sys.maxint
size_data=sock_data='';recv_size=8192
while total_len<size:
if len(remaining) != 0:
sock_data = remaining
else:
sock_data=self.csocket.recv(recv_size)
if not total_data:
if len(sock_data)>4:
size_data+=sock_data
size=struct.unpack('>i',size_data[:4])[0]
recv_size=size
if recv_size>524288:recv_size=524288
a = size_data
b = size_data[4:]
#print ' has: ' + a + 'appending: ' + b
total_data.append(b)
else:
size_data+=sock_data
else:
total_data.append(sock_data)
total_len=sum([len(i) for i in total_data ])
data = ''.join(total_data)
remaining = ""
if len(data) != size:
remaining = data[size:]
#print 'GOT EXTRA DATA!: ' + str(remaining)
data = data[:size]
finished = 0
#print 'packet actual size: ' + str(len(data))
if data: # add the data to the queue
#print 'got data: ' + data
try:
self.lock.acquire()
self.msgqueue.append(data)
finally:
self.lock.release()
#pass
else:
self.Close()
else:
print 'non socket message!!!'
except socket.error, (value, message):
#print "error: " + message
self.running = 0
#THIS IS WHAT IS TRIGGERED IF THE CLIENT DISCNNECTS
self.msgqueue.append( 'client closed!@#$%' )
def Send(self,msg):
if self.running:
try:
self.csocket.sendall(struct.pack('>i',len(msg)) + msg)
#print 'sending a packet of length: ' + str(len(msg))
except socket.error, (value,message):
print "send error: " + message
self.Close()
else:
print 'attempted to send from a closed client thread.'
def Close(self):
#self.Parent.lock.acquire()
try:
self.Parent.threads.remove(self)
except:
print 'networklib: unable to remove self from network thread list.'
#self.Parent.lock.release()
self.csocket.close()
self.running = False
def GetMessage(self):
o = None
try:
self.Parent.lock.acquire()
if len(self.msgqueue) > 0:
o = self.msgqueue.pop(0)
finally:
self.Parent.lock.release()
return o
class pyNetClient:
"Simple-To-Use Network Client"
def __init__(self):
self.HOST = 'localhost'
self.PORT = 21000
self.BUFSIZ = 1024
self.ADDR = (self.HOST,self.PORT)
self.csock = None
self.thread = None
self.lock = threading.Lock()
self.msgqueue = []
self.Running = 1
def Connect(self,adr):
self.ADDR = adr
self.csock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.csock.connect(self.ADDR)
#csock.send('yo')
#csock.close()
self.thread = pyNetClientThread(self)
self.thread.start()
def Send(self, msg):
try:
self.csock.sendall(struct.pack('>i',len(msg))+msg)
except socket.error, (value, message):
pass
def Close(self):
self.Running = 0
self.thread.running = 0
self.thread = None
print 'networklib: Closing Client Network Socket.'
def GetMessage(self):
o = None
try:
self.lock.acquire()
if len(self.msgqueue) > 0:
o = self.msgqueue.pop(0)
finally:
self.lock.release()
return o
def Connected(self):
return self.thread.running
class pyNetClientThread(threading.Thread):
"thread listener for client"
def __init__(self,parent):
threading.Thread.__init__(self)
self.Parent = parent
self.running = 1
def run(self):
while self.running:
try:
inputready,outputready,exceptready = select.select([self.Parent.csock],[],[],2)
for s in inputready:
if s == self.Parent.csock:
finished = 0
remaining = ""
while not finished:
finished = 1 # preset to finished, is reset if theres remaining data
total_len=0;total_data=[];size=sys.maxint
size_data=sock_data='';recv_size=8192
while total_len<size:
if len(remaining) != 0:
sock_data = remaining
else:
sock_data=self.Parent.csock.recv(recv_size)
if not total_data:
if len(sock_data)>4:
size_data+=sock_data
size=struct.unpack('>i',size_data[:4])[0]
#print 'packet of size: ' + str(size)
recv_size=size
if recv_size>524288:recv_size=524288
a = size_data
b = size_data[4:]
#print ' has: ' + a + 'appending: ' + b
total_data.append(b)
else:
size_data+=sock_data
else:
#print 'else appending: ' + sock_data
total_data.append(sock_data)
total_len=sum([len(i) for i in total_data ])
data = ''.join(total_data)
remaining = ""
if len(data) != size:
remaining = data[size:]
#print 'GOT EXTRA DATA!: ' + str(remaining)
data = data[:size]
finished = 0
#print 'packet actual size: ' + str(len(data))
if data:
#print 'got ' + data
try:
self.Parent.lock.acquire()
#print 'appending: ' + str(data)
self.Parent.msgqueue.append(data)
finally:
self.Parent.lock.release()
else:
#print 'get error'
self.running = 0
else:
print 'client got NON self.Parent.csock event!!!'
except socket.error, (value, message):
print 'got exception ' + message
self.running = 0
nserver = networklib.pyNetServer()
nserver.Start(6000)
msgs = nserver.GetMessages()
for clnt, msg in msgs:
if msg == "-disconnected-":
print 'client disconnected'
msgo = pickle.loads(msg) #convert the message into an instance of an object
if msgo[0] == "join": pass
client = networklib.pyNetClient()
client.Connect(( socket.gethostname() , 6000)) #connects localhost
client.Send( pickle.dumps( ("join", '' ) ) ) # this is how to send a packet
#heres the loop that peels off messages and allows you to do actions on them (messages from the server)
o = self.client.GetMessage()
if o != None:
#print 'new packet!: ' + str(o)
nobj = pickle.loads(o)
if nobj[0] == "pname":
print 'my name is!: ' + str(nobj[1])