Network Programming 2
CS 493/693 Lecture,
Dr. Lawlor, 2006/01/25
Writing TCP Code
One can imagine lots of programming interfaces for talking to the
network, and there are in fact lots of totally different interfaces for
talking on NetBIOS, AppleTalk, etc. But suprisingly there's basically
only one major programming interface used for talking on a TCP/IP network: Berkeley sockets.
The Berkely sockets interface is implemented in:
- All flavors of UNIX, including Linux, Mac OS X, Solaris, all BSD flavors, etc.
- Windows 95 and higher, as "winsock".
Brian Hall, or "Beej", maintains the definitive readable introduction to Berkeley sockets programming, Beej's Guide to Network Programming. He's got a zillion examples and a readable style. Go there.
Bare Berkeley sockets are pretty tricky and ugly, especially for
creating connections. The problem is Berkeley sockets support all
sorts of other protocols, addressing modes, and other features like raw
sockets that have serious security implications. But when I write
TCP code, I find it a lot easier to use my own little library of public
domain utility routines called "osl/socket.h". It's way too nasty
to write portable Berkeley code for basic TCP, so I'll give examples
using my library.
My library uses a few funny datatypes:
- SOCKET: datatype for a "socket": one end of a network connection between two machines. This is actually just an int.
- skt_ip_t: datatype for an IP address. It's just 4 bytes.
To connect to a server "serverName" at TCP port 8080, and send some data to it, you'd call:
- skt_ip_t ip=skt_lookup_ip(serverName); to look up the server's IP address.
- SOCKET s=skt_connect(ip,8080,60); to connect to that
server. "8080" is the TCP port number. "60" is the timeout
in seconds.
- skt_sendN(s,"hello",5);
to send the 5-byte string "hello" to the other side. You can now
repeatedly send and receive data with the other side.
- skt_close(s); to close the socket afterwards.
Easy, right? The same program is a great deal longer in pure
Berkeley sockets, since you've got to deal with error handling (and not
all errors are fatal!), a long and complicated address setup process,
etc.
To create a network server, you'd call:
- SERVER_SOCKET serv=skt_server(&port); to create a
"server socket" listening on this TCP port. A server socket is not a regular socket--it's just a handle you can use to wait for incoming connections on.
- SOCKET s=skt_accept(serv,&client_ip,&client_port);
waits until somebody connects to your port. This routine returns
a regular socket you can use to talk to that somebody. You can
actually repeatedly call skt_accept to talk to many different
clients--even simultaniously.
- skt_recvN(s,buf,5); reads 5 bytes off the network from the client. You can again repeatedly send and receive data with the other side.
- skt_close(s); closes our connection with that client.
- skt_close(serv); stops listening for new clients.
Check out tinyclient.cpp and tinyserver.cpp in the hw1 support directory, which do nothing but make these exact calls.