[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