Repositoryserver module

andy andy at eastonwest.co.uk
Tue Jan 7 20:56:48 CET 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