Breaking Down a Simple Python App
by Phillip Watts
June 16, 2009
|
Join us as we work with a simple client/server application and break down the code behind it.
|
Introduction
A Python Client/Server Tutorial
by Phillip Watts
There can be many reasons why you might need a
client/server application. For a simple example, purchasing for
a small retail chain might need up to the minute stock
levels on a central server. The point-of-sale application in
the stores would then need to post inventory transactions to
the central server in real-time.
This application can easily be coded in Python with
performance levels of thousands of transactions per second
on a desktop PC. Simple sample programs for the server and
client sides are listed below, with discussions following.
1 #!/usr/bin/env python
2 # a simple TCP server
3 from socket import *
4 import sys
5 import os
6 BUFSIZ = 4096
7 HOST = ''
8 PORT = 29876
9 ADDR = (HOST,PORT)
10 class ServCmd:
11 def __init__(s):
12 s.__serv = socket( AF_INET,SOCK_STREAM)
13 s.__serv.bind((ADDR))
14 s.__cli = None
15 s.__imlistening = 0
16 s.__improcessing = 0
17 s.__run()
18 def __run(s):
19 s.__imlistening = 1
20 while s.__imlistening:
21 s.__listen()
22 s.__improcessing = 1
23 while s.__improcessing:
24 s.__procCmd()
25 s.__cli.close()
26 s.__serv.close()
27 def __listen(s):
28 s.__serv.listen(5)
29 print '...listening'
30 cli,addr = s.__serv.accept()
31 s.__cli = cli
32 print '...connected: ', addr
33 def __procCmd(s):
34 cmd = s.__cli.recv(BUFSIZ)
35 if not cmd: return
36 print cmd
37 s.__servCmd(cmd)
38 if s.__improcessing:
39 proc = os.popen(cmd)
40 outp = proc.read()
41 if outp:
42 s.__cli.send(outp)
43 else :
44 s.__cli.send('good')
45 def __servCmd(s,cmd):
46 cmd = cmd.strip()
47 if cmd == 'BYE':
48 s.__improcessing = 0
49 if __name__ == '__main__':
50 serv = ServCmd()
Now lets take a look at the code breakdown.
The server program:
Line 3 imports the socket module. The current
documentation for the Python socket module begins at: http://
docs.python.org/library/socket.html
Lines 7 - 9 create the constants needed for a connection.
The port number is completely arbitrary and outside the
range of commonly used ports.
Line 12 creates a TCP socket.
Line 13 "binds" the new socket to the chosen port.
With these few lines of code, the server is now ready to
begin "listening" on that port for a client connection.
The __run() method "listens" while
__imlistening is true, lines 20 - 25. It processes commands
from the client, lines 23 -24, while __improcessing is
true.
Lines 27 - 30 do the actual listening.
Line 30, socket.accept() is a blocking call.
That is, it will wait forever for a connection. When a
connection from a client arrives, accept()
returns a tuple: an instance of the client connection, which
is saved as s.__cli, and the IP address of the
client.
Line 34 retrieves the contents of the message sent by
the client. Lines 39 and 40 attempt to execute the content
as a command. Lines 42 or 44 send a message back to the
client. And if the the message is "BYE", line 25 closes the
connection.
Let us review:
from socket import * - import the socket module
HOST = ''
PORT = 29876
ADDR = (HOST,PORT) - create a port constant
serv = socket( AF_INET,
SOCK_STREAM) - create a TCP socket
serv.bind((ADDR)) - bind the socket to the port
serv.listen(5) - listen to that port
cli,addr = serv.accept() - read a tcp packet
cmd = cli.recv(BUFSIZ) - get data from the packet
cli.send(outp) - send message to the client
cli.close() - close the connection
serv.close() - close the server socket
Breaking Down a Simple Python App
The Client Side
|