Repositoryserver module
andy
andy at eastonwest.co.uk
Tue Jan 7 14:56:48 EST 2003
Here's the repository server code I've been working on.
After thinking a bit more about the name I chose, I now feel that Scoreboard
or Whiteboard would be more appropriate.
Please bear in mind that it's really *very* primitive at this time, and a bit
shaky in (possibly many) places. I've only just got my head around socket
programming, so I've probably made some stupid blunders here and there.
I have plans to build upon this to add features such as: authentication,
security, pickling, persistency, separate name-spaces and so on. The eval()
style conversion of the request keys will be replaced with something less
dangerous, or at least vetted for safety some how...
Eventually, I'll wrap it all up in a class, one for the server and one for the
client.
The server is first, followed by a test-client...
regards,
-andyj
# repositoryserver.py
""" allows remote read/write access to a dictionary over ip sockets"""
import socket,time,string
repository={} # Place to store data
cycle=0 # mostly to show it's still ticking over
class connexion:
def __init__(self,conn,addr):
self.conn=conn
self.addr=addr
self.packetsize=1024
self.conn.setblocking(0)
def send(self,msg):
""" Sends msg in one go """
self.conn.sendall(msg)
def wait_recv(self):
""" Waits for input to begin and then reads the stream 'dry' """
# This is a very immature approach though
# Wait for input to begin
buf=""
while buf=="":
try:
buf=self.conn.recv(self.packetsize)
except:
pass
# Wait for rest of input to come in
buf2="*"
while buf2<>"":
try:
buf2=self.conn.recv(self.packetsize)
buf=buf+buf2
except:
buf2=""
self.conn.recv(self.packetsize)
return buf
def recv(self):
""" Checks for input on stream and if there is any, reads it 'dry' """
# Get input
buf=""
try:
buf=self.conn.recv(self.packetsize)
except:
buf=""
# Wait for rest of input to come in
buf2="*"
while buf<>"" and buf2<>"":
try:
buf2=self.conn.recv(self.packetsize)
buf=buf+buf2
except:
buf2=""
return buf
def process(self,req):
global repository
print "Cycle %i Process request %s from %s" % (cycle,req,self.conn)
req=string.strip(req)
if req<>"":
try:
dict=eval(req)
except:
dict={}
if dict.has_key("request") and dict.has_key("keys"):
if dict["request"]=="set":
dict["response"]="ok"
for k in dict["keys"].keys():
try:
repository[k]=dict["keys"][k]
except:
dict["response"]="no"
dict["reason"]="Failed to set key"
dict["key"]=k
print repr(dict)
self.conn.send(repr(dict))
elif dict["request"]=="query":
dict["response"]="ok"
for k in dict["keys"].keys():
dict["response"]="ok"
if repository.has_key(k):
dict["keys"][k]=repository[k]
else:
dict["response"]="no"
dict["reason"]="No such key"
dict["key"]=k
print repr(dict)
self.conn.send(repr(dict))
else:
print "Error - malformed request"
self.conn.send("Error - malformed request")
def checkNewConnexions():
try:
conn,addr=s.accept()
print conn,addr
except:
return None
return connexion(conn,addr)
HOST = "" # localhost
PORT = 50007
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.setblocking(0)
s.listen(1)
print s
try:
clients=[]
quit=0
cycle=0
while not quit:
time.sleep(0.001) # Don't hog the cpu
c=checkNewConnexions()
if c<>None:
print "Adding new client..."
clients.append(c) # Add client to list
for c in clients:
req=c.recv() # Read any incoming request
if req<>"":
c.process(req)
cycle+=1
for c in clients:
c.conn.close()
finally:
print "Closing connections..."
for c in clients:
c.conn.close()
print "Closing socket..."
s.close()
#################################################
# repcount.py - a repositoryserver.py client
# simply increments a key by one in a loop
import socket,time,string
def request(inp,blocking=0):
if inp<>"":
s.sendall(inp)
# Get response from server
resp=""
buf="*"
print "waiting for response"
# need to tidy up timeout here...
time.sleep(0.02)
t=time.time()+5
while len(resp)==0 and t>time.time():
buf="*"
while len(buf) and t>time.time():
try:
buf=s.recv(1024)
print "got",buf
resp=resp+buf
except:
buf=""
print "Sleeping"
time.sleep(0.002)
return resp
else:
return ""
def query(key):
print "Query",key
resp=request("{'request':'query','keys':{'%s':None}}" % (key,))
dict=eval(string.strip(resp))
if dict["response"]=="ok":
return dict["keys"][key]
else:
return None
def set(key,v):
print "Set",key,"=",v
resp=""
while resp=="":
resp=request("{'request':'set','keys':{'%s':%s}}" % (key,repr(v)))
print resp
dict=eval(string.strip(resp))
if dict["response"]=="ok":
return 1
else:
return 0
HOST = "192.168.92.1" # my workstation's ip
PORT = 50007
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.setblocking(0)
try:
inp=""
n=1
# Get key value
m=query("test")
if m==None: m=0
while inp<>"QUIT\r\n":
print m
# Set key value
set("test",m)
m+=1
finally:
print "Closing connection..."
s.close()
More information about the Python-list
mailing list