IPC
If you need fast IPC between two processes on one machine, you should look into whatever form of shared memory the platform offers. A simple protocol based around shared memory and locks or semaphores is by far the fastest technique.
If you do decide to use sockets, bind the "server" socket to 'localhost' . On most platforms, this will take a shortcut around a couple of layers of network code and be quite a bit faster.
|
Creating a Socket
Roughly speaking, when you clicked on the link that brought you to this page, your browser did something like the following:
#create an INET, STREAMing socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# - the normal http port
s.connect(("www.mcmillan-inc.com", 80))
When the connect completes, the socket s can now be used to send in a request for the text of this page. The same socket will read the reply, and then be destroyed. That's right - destroyed. Client sockets are normally only used for one exchange (or a small set of sequential exchanges).
What happens in the web server is a bit more complex. First, the web server creates a "server socket".
#create an INET, STREAMing socket
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
#bind the socket to a public host,
# and a well-known port
serversocket.bind((socket.gethostname(), 80))
#become a server socket
serversocket.listen(5)
A couple things to notice: we used socket.gethostname() so that the socket would be visible to the outside world. On a machine with only one address (most machines), we could also
have used s.bind(('', 80)) . If we had used s.bind(('localhost', 80)) or s.bind(('127.0.0.1', 80)) we would still have a "server" socket, but one that was only visible within the same machine.
A second thing to note: low number ports are usually reserved for "well known" services (HTTP, SNMP etc). If you're playing around, use a nice high number (4 digits).
Finally, the arg to listen tells the socket library that we want it to queue up as many as 5 connect requests (the normal max) before refusing outside connections. If the rest of the code is written properly, that should be plenty.
OK, now we have a "server" socket, listening on port 80. Now we enter the mainloop of the web server:
while 1:
#accept connections from outside
(clientsocket, address) = serversocket.accept()
#now do something with the clientsocket
#in this case, we'll pretend this is a threaded server
ct = client_thread(clientsocket)
ct.run()
There's actually 3 general ways in which this loop could work - dispatching a thread to handle clientsocket , create a new process to handle clientsocket , or restructure this app to use non-blocking sockets, and mulitplex between our "server" socket and any active clientsocket s using select . More about that later. The important thing to understand now is this: this is all a "server" socket does. It doesn't send any data. It doesn't receive any data. It just produces "client" sockets. Each clientsocket is created in response to some other "client" socket doing a connect() to the host and port we're bound to. As soon as we've created that clientsocket , we go back to listening for more connections. The two "clients" are free to chat it up - they are using some dynamically allocated port which will be recycled when the conversation ends.
NEXT: Using Sockets
|