Welcome to the Network Programming mini-Tutorial for Linux


dot.jpgWhat I Assume

I assume that you know what a network is and know about the basic networking protocols. I also assume that you know that this mini-tutorial is mostly geared towards TCP/IP and UDP/IP programming. Furthermore, I go on to assume that you know that no web site tutorial can be a valid substitute for a good book.

dot.jpgThe Disclaimer

I know that everyone must be responsible for what he/she says; but, I am really doing this out of the kindness of my heart during my free time. And thus, I want you to know that this mini-tutorial is not error proof and is more likely to be error prone. In accordance with these facts, do not depend on this site like you would on your family to save your life during a time of crisis. Take everything that I say/type with a grain of salt and know with the fullness of your soul that I will not take responsibility for any blunders that this mini-tutorial may cause in your life. If there are any errors, please e-mail me and I will correct it as soon as possible.

dot.jpgWarning

Do not use the information presented here to hack or otherwise damage or create mischief for others on any network. If you do, I will be forced to put a fifty thousand year curse on you that will make your feet grow to abnormal proportions. Believe you me, abnormally big feet is a vicious torture for anyone. (You will never be able to dance again... ha, ha, ha.)

dot.jpgNotation

I make use of a make-shift pseudo notation throughout this document. I refer to functions by their name followed by two parenthesis without parameters. ( i.e. socket(), bind() ) This does not mean that the functions lack parameters. It is just that it is easier to type socket() fifty times in a paragraph than socket(family, blah, blah). Also, I will place important terms between double quotations. ( i.e. "datagram", "protocol") Single quotations are incorrectly placed all over the place. I use them rather liberally without just cause.

dot.jpgThe Basics

Linux utilizes an abstractation called "sockets" to represent the interface between the programmer and the operating system's network functionality. The main idea behind sockets is to encapsulate state information in a protected environment and still easily allow customization and control of said information. Sockets usually send data either by "datagram" or by "streams." You can view a datagram as an array of bytes with an appropriate header that will describe the source and destination of the message. This header may or may not contain additional protocol specific information. This leads us to ask ourselves what a "protocol" is. Protocols are commonly agreed upon methods used to transport data. Imagine two people agreeing on how to send smoke signals when they are together. The type of signals that they agree upon and the order in which to use them is the protocol. When they are apart, they must adhere to the protocol; else, they will soon become confused of each others intention. As for streams, imagine a setting sort of like the phone system. One must 'call' another system and become "connected" in order for information to be accepted. And following that model, one can refuse to become connected by not picking up the phone or by picking it up and then abruptly hanging up. Such actions can cause the person placing the call to obtain a 'connection refused' message. Once connected, data is transported like water in a pipe. Anything placed in one end will emerge out of the other end in the same order that is was placed. (This is unlike datagrams which do not guarantee the order in which data is received, even if it is sent in order.) Streams also tend to be "reliable" because of this aspect. All data must arrive in order, so all data must arrive.

dot.jpgBeginning to Code

To begin our excursion, we must first allocate a socket. We do this through a call to the system function "int socket(int, int, int)." The parameters passed to socket() are the family, the socket type, and the protocol. Since this is a simple tutorial, we will only be using the AF_INET family, the internet suite of protocols. (From now on, just put AF_INET into the first parameter of socket() and be satisfied. I might explain a little about families later, but I make no guarantees to do so.) The two types that we will be concerned with are SOCK_STREAM (The protocols that are reliable and connection based.) and SOCK_DGRAM (The protocols that fall under the category of datagrams.). (There are actually a few more options that will be explained later on.) And the protocol parameter will be an enumerated integer representing a protocol. You can obtain the protocol number in two ways. (There might be more that I do not know of.) First and foremost, you can make a call to the function "getprotobyname(char*)" and pass to it a string that represents the protocol. Secondly, we can use the constants defined in the header file "/usr/include/linux/in.h." The call to socket() will either return a negative value which will indicate an error or an integer that represents a file descriptor that represents the socket. Save this integer, for we will must make use of it in our program to manipulate the state of the socket. For stream-based protocols, we must call "connect(int, sockaddr*, int)" after we allocate the socket to 'call' another host before we can even think of transferring data. The first parameter passed to connect() is the integer that we saved from the call to socket(). The second parameter is a C structure that represents, in a protocol independent manner, the machine or device to connect to. The last parameter is the size of the structure that we are passing in, which can be obtained by using the C sizeof() operator.

Another little detail that we must take care of is something called the "endianess" of a host cpu. x86 cpus are "little endian" while 68K cpus are "big endian." Little endians store multi-byte words (simply a means of naming a group of bytes. i.e. a word can be 2 bytes on one machine and 4 on another) with the "most significant byte" aligned to the highest address while big ones store the msb aligned to the lowest address. If this is too confusing, just remember to use ntohs() when reading a 2-byte value from the network and htons() before writing it. You must also use ntohl() and htonl() for 4-byte values.

dot.jpgThe Transport Control Protocol

TCP, the "Transport Control Protocol" is a reliable connection based streaming protocol that 'rides on top' of IP. What do I mean by 'rides' you ask? It has to do with the dubious fact that protocols can be defined relative to each other. Following our Indian smoke analogy, suppose our two friends were joined by a third and a fourth brave. We can already predict the disaster that will ensue. Smoke signals soon become very confusing. Now we can adopt a sort of sub-protocol to alleviate this slight problem. One such scheme is to have each indian send a prefix to describe which brave he means the following message to be interpreted by. He may also wish to send a postfix so he can tell the other brave to ignore the next message, etc.

There is an additional benefit to using the TCP protocol. To make this clear, we must introduce the notion of "ports." A port is a theoretical entity designed to broker communications between multiple applications on different hosts. (Because each host may have many applications running and communicating with the same application on another host.) An example would be two users on a Linux server trying to ftp (incorrect usage of ftp as a verb, no doubt) files from the same FreeDOS server. Since the users share the same i.p. address, the FreeDOS server would have no idea how to direct the data through an i.p. only situation. Luckily, the servers are using TCP which facilitates the designation of a different port to each users' ftp application. Now, the FreeDOS server can direct each file according to i.p. address and port number and be sure that the Linux server will distribute the files to the correct user. In accordance, we know that sending data using TCP neccesitates us to not only specify which host we want our data to go to but also the application connected to the port. Simple, no?

Before we jump headlong into coding, I must seek to distinguish between "server" and "client" sockets. The server socket is related to applications on servers that offer a service, such as the ftp daemon in our example. The client socket is related to the socket that seeks the service, such as the ftp applications running our Linux server. O.K., put your cap on and let's dive. ;-)

The steps to creating and connecting a TCP/IP socket can are:

1.      Call "socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)" or call "getprotobyname("TCP")" and obtain the returned "struct protoent *" and then call "socket(AF_INET, SOCK_STREAM, protoent->p_proto)."

2.      Allocate and clear a "sockaddr" structure.

3.      Place the address and port of the host you wish to connect to in the structure.

4.      Then call connect(). Connect will return a negative number if there is a failure; otherwise, it has been a success. You can now write() or read() to the socket like a regular file.

5.      You must close() the socket when your are through using it to release system resources related to it.

These are the steps to creating a server socket.

1.      Perform steps 1 and 2 above.

2.      Put the port that you want to listen on in the structure and "INADDR_ANY" into the i.p. address data member of said structure.

3.      Call bind() to tell the system to allocate that port to your socket. Only one socket can be listening to a port at any given time. (There are exceptions that can safely be ignored for now.)

4.      Call listen() to tell the system to begin listening for connections.

5.      Allocate another "sockaddr" structure to store the address of the client connecting to your server socket and clear it. (Fill the structure with zeros.) Also, allocate an integer and store the sizeof() the structure allocated in this step in it.

6.      Start accepting connections by calling accept() with the address of your structure allocated in step 5 and the address of the integer created in step 5. When accept() returns, it will return a -1 if there is an error or a positive integer representing the socket you can use to communicate with the client. The structure and integer from step 5 will contain the address of the client and the sizeof the information stored there.

The following is some sample code of both a server and client socket built into one application: tcpexample.c

dot.jpgThe User Datagram Protocol

UDP, the user datagram protocol (sometimes called the unreliable datagram protocol for good reason) is an unreliable "connectionless" datagram based protocol. It is a fairly simple protocol that does not need very much to be explained about it for one to gain a good working understanding of it. In fact, the only worthwhile feature that I will point out is that it facilitates ports just like its cousin TCP. (Note: The process for allocating a socket on the server and client is the same. There is no distinct differences in allocation like there is in the TCP model.)

Follow these steps to create and utilize UDP sockets:

1.      Call "socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)" or use getprotobyname() as above, replacing "TCP" with "UDP", obviously.

2.      Create a "sockaddr" and clear it.

3.      Place the port you wish to obtain data from in the "sin_port" data member of the structure that you created in step 2.

4.      Bind the socket using the structure from step 2.

5.      Create another "sockaddr" structure and an integer. Store the sizeof() the new structure into the integer.

6.      Call recvfrom(), passing in the address of the structure from step 5 and the address of the integer from said step, to read from the socket and call sendto() to send data to other hosts.

The following is a UDP example: udpexample.c

. dot.jpgCorrections and Other Misdemeanors

dot.jpgOther Great Linux Programming Sites

dot.jpgPeople Who Helped Me

dot.jpgInteresting Books I Used

dot.jpgMore Stuff From Me

dot.jpgTrademarks

dot.jpgContact Information

If you have any questions, comments, or suggestions, please e-mail Xengren@Yahoo.com.

You are visitor #.


The Linux Project

Hey, it's free and fabulous.

Best experienced with

Click here to start.

The FreeDOS Project

FreeDOS

Hey, it's free.

This site is best viewed with

Download Netscape Now!