[Tutor] Socket Programming
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Sun Jul 31 08:11:04 CEST 2005
> I have no idea how to get the server to receive and print a message or
> for the client to send the message. Does anyone know of some good python
> networking tutorials designed for newbies? (Not ones on
> www.awaretek.com. They seem to expect you to know some things that I
> don't even know about.)
Hi Joe,
Before we start: it might be easier to start off with a high-level
networking protocol, like XMLRPC. There are examples of making xmlrpc
clients and servers in the Library documentation:
http://www.python.org/doc/lib/xmlrpc-client-example.html
http://www.python.org/doc/lib/simple-xmlrpc-servers.html
Sockets tend to be pretty low-level at times, with its own set of issues.
Have you seen AMK's Socket HOWTO tutorial already?
http://www.amk.ca/python/howto/sockets/
... wait, ok, I see, your example code below appears to come from the
Socket HOWTO tutorial after all! Ok, so you're trying those examples now?
Let's take a closer look.
> #Client
> import socket
> #create an INET, STREAMing socket
> s = socket.socket(
> socket.AF_INET, socket.SOCK_STREAM)
> s.connect(("localhost", 2000))
> s.send('hello!'[totalsent:])
The last statement looks a little weird, since 'totalsent' isn't defined.
Are you just trying to send a message to the server? If so, then:
######
s.send("hello!\n")
######
should do something, although there's no guarantee that all seven bytes
will go across the network. So something like:
######
bytesReallySent = 0
while bytesReallySent != len('hello!\n'):
bytesReallySent += s.send("hello!\n"[bytesReallySent:])
######
might work better: it will continue calling s.send() until all the bytes
in the message have been sent over. Of course, this is really paranoid:
the socket probably will be able to pass all seven bytes at once, but for
longer strings, a socket's send() method doesn't guarantee how much it can
send at once.
As you can see, this is a really low-level detail sort of thing: we can
avoid some of these issues by using a higher-level file interface:
######
import socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 2000))
f = s.makefile()
######
At this point, f is a file-like object, and we should be able to use a
file's write() method:
######
f.write('hello!\n')
######
and the high-level interface should guarantee that this will work in one
shot.
However, even then, we may need to worry about buffering and blocking
issues, so we may need to use a flush() to guarantee that things are
passed across the network.
######
f.flush()
######
Let's look at the server side code:
> #Server
> import 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(), 2000))
> #become a server socket
> serversocket.listen(5)
>
> while 1:
> #accept connections from outside
> clientsocket, address = serversocket.accept()
> serversocket.recv()
^^^^^^^^^^^^
I believe the last statement is off; you probably want to use the
'clientsocket' here, not 'serversocket'.
The idea is that there's a central serversocket that listens to a
particular port, and that's the socket that's being bound in:
serversocket.bind((socket.gethostname(), 2000))
And every time a client comes, it talks to the serversocket. The
serversocket accepts the connection, but delegates communication off to
the clientsocket instead, the one that gets returned from
serversocket.accept():
clientsocket, address = serversocket.accept()
So:
######
clientsocket.recv()
######
should work better.
The Socket Programming HOWTO talks about the difference between the
"server socket" and a "client socket" in a little more detail, near the
end of Section 2.
If you have more questions, please feel free to ask!
More information about the Tutor
mailing list