Net Program Linux
Volume Number: 16
Issue Number: 1
Column Tag: Linux Development
Net Program Linux
by Giovanna Pavarani
Contributing Editor, Michael Swan
How programs communicate through sockets in a
client-server architecture
My first personal computer was a Mac IIsi and I've always had a Mac for fun and
personal use, but, as a programmer, I was born in a UNIX environment and there I
grew up for my job. In particular, I spent lot of time implementing network protocols
and writing software for client-server architectures. When I heard, near two years
ago, that there was a Linux implementation for PPC I couldn't resist and I cleared a
little space on my hard disk to install it and try it.
There is a lot of talk nowadays about Mac OS X, Linux and its Macintosh incarnations,
Darwin, OpenSource, networking technologies, and you've seen it in the pages of
MacTech Magazine too. So, if you are just curious, or you plan to write networking
code in a UNIX-like environment, maybe this article can give you some starting points
and/or some hints.
Background
In this article I assume that you have a working UNIX-like environment and some
familiarity with it. If this is not your case don't worry! There are lots of resources on
the net to help you fulfill these requirements. A good starting point could be the official
site of the MkLinux community: http://www.mklinux.org. This site can help you
choose the right Linux flavor for your machine (PPC or 68K, PCI or NuBus, old or
brand new models ...) and gives you pointers to the different distributions for code and
installation instructions. For a User's Guide and other useful docs just select the link
to the Linux Documentation Project. Then remember to install and configure the
network stuff, the system manual pages, the compiler and debugger, and a friendly GUI
:-) (all freely included in nearly all distributions). Manual pages are very important
because you can use them to know more about a command or a system call. If you want
to know what is and how it works the socket() call, for example, just type man socket
at the prompt; man man gives you details on how to use the man facility. At last, for
troubles, doubts or questions not answered by the site or manual pages, there are very
helpful and polite dedicated mailing lists.
On my Mac, I've installed a MkLinux DR3 distribution complete with manual pages,
development libraries and the GNU C Compiler and debugger. All the article's examples
have been tested on this system and on a RedHat 6.0 Intel box, but the concepts and the
code are so general that it's quite easy to use them in another UNIX-like operating
system, even not Mac specific. You don't need a real network to test the examples, you
can launch the programs on the same machine, provided that you have installed the
network protocol stack and configured your computer.
Socket Basics
In a Unix like system, communications take place between endpoints called sockets
within a communication domain. Domains are abstractions which imply both an
addressing structure (address family) and a set of protocols implementing the various
socket types within the domain (protocol family). The two most important domains are
the UNIX domain and the INTERNET domain. They both allow processes to communicate
but only the INTERNET domain allows communications between two machines. In the
UNIX domain the socket is identified by a path name within the file system name space
and communication is permitted between any two processes that reside on the same
machine and are able to access the socket pathname. The INTERNET domain allows
communication between processes on separate machines with the Internet protocol
family; the addresses consist of a machine network address and an identifying number
called port. The type of the socket describes the semantics of the communication and its
properties: reliability, ordering and prevention of messages duplication. The most
known socket types are:
Stream socket. This type of socket provides a bi-directional, reliable,
error-free, sequenced and non duplicated flow of data without record
boundaries. Stream communication implies a connection.
Datagram socket. Datagram sockets provide a bi-directional flow of
data but don't guarantee that the datagrams will be received in the same order
they were transmitted, or that they won't be duplicated. Record boundaries in
data are preserved and a datagram communication doesn't imply a connection.
Raw socket. Raw sockets allow users direct access to a lower-level
protocol; they aren't for the general user but for those that intend to develop
new communication protocols or use some of the more particular aspects of an
existing protocol.
The most common use of sockets is in a client-server architecture. In this model,
client applications request services from a server process. The protocol implemented
at both ends of the connection can be symmetric or asymmetric. In a symmetric
protocol, both ends may play the server or client roles (e.g. the TELNET protocol); in
an asymmetric protocol one end is always the server and the other is always the client
(e.g. the FTP protocol).
In this article I'll give you complete examples of client and server processes using
stream and datagram sockets in the INTERNET domain.
Opening a socket is quite easy:
int s = socket(int domain, int type, int protocol);
This system call creates a socket in the specified domain (AF_UNIX, Address Format
UNIX, or AF_INET, Address Format INTERNET), of the specified type (SOCK_DGRAM,
for datagram socket, or SOCK_STREAM, for stream socket). We can specify a protocol
too, but leaving it to 0 is usually the best choice: the system will choose the
appropriate protocol in the domain that can support the requested type, usually UDP
for datagrams and TCP for streams.
Before accepting a connection or receiving a datagram, a socket must first bind to a
name or address within the communication domain:
bind(int s, struct sockaddr *name, int namelen);
This call binds to a previously created socket s a name: an Internet address and port
number in the INTERNET domain or a path name and a family in the UNIX domain.
To send datagrams a client uses:
sendto(int s, void *msg,int len, unsigned int flags, struct \ sockaddr
*to, int tolen);
where to is the destination address.
To receive datagrams a server uses:
read(int s, void *buf, size_t count);
or, when it needs to know the sender address:
recvfrom(int s,void *msg, int len,int flags,struct sockaddr \ *from,
int *fromlen);
To establish a connection versus a server, a client performs a:
connect(int s, struct sockaddr *server, int serverlen);
The server parameter contains the UNIX pathname or the Internet address and port
number of the server to which the client wishes to talk.
To accept a connection from a client, a server must perform two more steps after the
bind() call:
listen(int s, int pending);
int newsock = accept (int s, struct sockaddr *from, int \ *fromlen);
With the first call, a server indicates that it's ready to listen for incoming connection
requests on the socket s; pending is the maximum number of connections that may be