SimpleClientServer

Using libraries

The code

This example is about the simplest code anyone could devise. We are not looking today in order to learn how to write networking code, but to have the simplest possible example that needs networking libraries.

server.c

This is just a server, that opens up a port to listen on a network following the tCP protocol, and when a query arrives to run the program readdir and send its result as a reply.

readdir.c

This has nothing to do with networking, and is just a program to be run when requested.

client.c

This sends a query to a specified host and port. We will be doing a lot of this later, and just need a program to illustrate the idea for now.

compile-it.sh

This is the point of the example at the moment, it shows that to compile both of our programs we need to ask the system to link them together with various programs that are part of the nsl library and the sockets library.

doit.sh

This (we may do it in class) just starts up the server, then starts up the client (as we will see, you MUST do it in this order), and then sends a simple query from the client to which the server responds.

tcp03.dump

This is a file captured by the program tcpdump as we will demonstrate (which in turn uses a library program called pcap for capturing network traffic.

tcp03.stak

This is the output of a (Java> program of mine called stak which analyzes the various layers of communication involved in running this client and server.

Just for kicks

You might browse the contents of the two libraries we use. The Unix command nm is used to learn the names of the programs that are contained in various libraries:

So look at what happened when I typed nm libnsl.so.1.txt , and nm libsocket.so.1.txt . These show all the programs (and other things like data sections) that are in the libraries, and from the names you can get an idea of what kinds of things the libraries know how to do.

If you are lucky you will never have to look inside one of these again:-


Code links

server.c
readdir.c
client.c
compile-it.sh
do-it.sh
tcp03.stak

Listings

server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>

#define PORT 		0x1234
#define DIRSIZE 	8192

main()
{
        char     dir[DIRSIZE];  /* used for incomming dir name, and
					outgoing data */
	int 	 sd, sd_current, cc, fromlen, tolen;
	int 	 addrlen;
	struct   sockaddr_in sin;
	struct   sockaddr_in pin;
 
	/* get an internet domain socket */
	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}

	/* complete the socket structure */
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons(PORT);

	/* bind the socket to the port number */
	if (bind(sd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
		perror("bind");
		exit(1);
	}

	/* show that we are willing to listen */
	if (listen(sd, 5) == -1) {
		perror("listen");
		exit(1);
	}
	/* wait for a client to talk to us */
        addrlen = sizeof(pin); 
	if ((sd_current = accept(sd, (struct sockaddr *)  &pin, &addrlen)) == -1) {
		perror("accept");
		exit(1);
	}
/* if you want to see the ip address and port of the client, uncomment the 
    next two lines */

       /*
printf("Hi there, from  %s#\n",inet_ntoa(pin.sin_addr));
printf("Coming from port %d\n",ntohs(pin.sin_port));
        */

	/* get a message from the client */
	if (recv(sd_current, dir, sizeof(dir), 0) == -1) {
		perror("recv");
		exit(1);
	}

        /* get the directory contents */
         read_dir(dir);
    
      /* strcat (dir," DUDE");
       */
	/* acknowledge the message, reply w/ the file names */
	if (send(sd_current, dir, strlen(dir), 0) == -1) {
		perror("send");
		exit(1);
	}

        /* close up both sockets */
	close(sd_current); close(sd);
        
        /* give client a chance to properly shutdown */
        sleep(1);
}

readdir.c
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

#define DIR_SIZE 8192

read_dir(dir)
char    *dir;   /* anticipate char dir[DIR_SIZE] */
{
        DIR * dirp;
        struct dirent *d;

        /* open directory */
        dirp = opendir(dir);
        if (dirp == NULL)
                return(0);

        /* stuff filenames into dir buffer */
        dir[0] = '\0';
        while (d = readdir(dirp))
                sprintf(dir, "%s%s\n", dir, d->d_name);

        /* return the result */
        closedir(dirp);
}

client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>

#define PORT        0x1234
/* REPLACE with your server machine name*/
#define HOST        "localhost"
#define DIRSIZE     8192

main(argc, argv)
int argc; char **argv;
{
        char hostname[100];
	char    dir[DIRSIZE];
	int	sd;
	struct sockaddr_in sin;
	struct sockaddr_in pin;
	struct hostent *hp;

        strcpy(hostname,HOST);
        if (argc>2)
            { strcpy(hostname,argv[2]); }

	/* go find out about the desired host machine */
	if ((hp = gethostbyname(hostname)) == 0) {
		perror("gethostbyname");
		exit(1);
	}

	/* fill in the socket structure with host information */
	memset(&pin, 0, sizeof(pin));
	pin.sin_family = AF_INET;
	pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
	pin.sin_port = htons(PORT);

	/* grab an Internet domain socket */
	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}

	/* connect to PORT on HOST */
	if (connect(sd,(struct sockaddr *)  &pin, sizeof(pin)) == -1) {
		perror("connect");
		exit(1);
	}

	/* send a message to the server PORT on machine HOST */
	if (send(sd, argv[1], strlen(argv[1]), 0) == -1) {
		perror("send");
		exit(1);
	}

        /* wait for a message to come back from the server */
        if (recv(sd, dir, DIRSIZE, 0) == -1) {
                perror("recv");
                exit(1);
        }

        /* spew-out the results and bail out of here! */
        printf("%s\n", dir);

	close(sd);
}

 


compile-it.sh
gcc -lnsl -lsocket -o client client.c
gcc -lnsl -lsocket -o server server.c readdir.c

do-it.sh
scp server spectral:
ssh spectral ./server
tcpdump -w tcp03.dump port 0x1234
./client hello there spectral.mscs.mu.edu

tcp03.stak
Parse  of a tcpdump file with parameters:
  (Magic:a1b2c3d4 Major:2 Minor:4 timezone:0 Junk:0 SnapLen:96 LinkType:1)

Capturing began at: Tue Sep 14 18:19:00 CDT 2010

[0.00000.00000](0.00000.00000)   CAPTURE-00000 66/66
PROVIDER:ether USER:ip <14+52>
Available bytes:66
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+32>
Available bytes:52
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:32 tos:0 id:10550 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <32+0>
     src:53205 dst:4660   S    s:0 l:0 a:0 w:49640 
PROVIDER:raw USER:none <0+-1>


[0.00017.00691](0.00017.00691)   CAPTURE-00001 66/66
PROVIDER:ether USER:ip <14+52>
Available bytes:66
src:00-0f-66-9d-f0-c1 dst:00-14-4f-80-e5-b8 type: 2048
PROVIDER:ip USER:tcp <20+32>
Available bytes:52
4    src:134.48.6.129 dst:192.168.1.6   hlen:20 len:32 tos:0 id:51809 ttl:53 protocol:6 CheckSum:2d03
PROVIDER:tcp USER:raw <32+0>
     src:4660 dst:53205   SA   s:0 l:0 a:1 w:49680 
PROVIDER:raw USER:none <0+-1>


[0.00017.00781](0.00000.00090)   CAPTURE-00002 54/54
PROVIDER:ether USER:ip <14+40>
Available bytes:54
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:40
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:20 tos:0 id:10551 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <20+0>
     src:53205 dst:4660    A   s:1 l:0 a:1 w:49680 
PROVIDER:raw USER:none <0+-1>


[0.00020.00817](0.00003.00036)   CAPTURE-00003 65/65
PROVIDER:ether USER:ip <14+51>
Available bytes:65
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+31>
Available bytes:51
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:31 tos:0 id:10552 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <20+11>
     src:53205 dst:4660 P  A   s:1 l:11 a:1 w:49680 P 
PROVIDER:raw USER:none <11+-1>
00000000   68 65 6c 6c 6f 20 74 68 65 72 65                 hello there

[0.00035.00770](0.00014.00953)   CAPTURE-00004 60/60
PROVIDER:ether USER:ip <14+46>
Available bytes:60
src:00-0f-66-9d-f0-c1 dst:00-14-4f-80-e5-b8 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:46
4    src:134.48.6.129 dst:192.168.1.6   hlen:20 len:20 tos:0 id:51810 ttl:53 protocol:6 CheckSum:2d0e
PROVIDER:tcp USER:raw <20+0>
     src:4660 dst:53205    A   s:1 l:0 a:12 w:49680 
PROVIDER:raw USER:none <6+-1>
00000000   00 00 94 d9 db f3                                ......

[0.00036.00294](0.00000.00524)   CAPTURE-00005 65/65
PROVIDER:ether USER:ip <14+51>
Available bytes:65
src:00-0f-66-9d-f0-c1 dst:00-14-4f-80-e5-b8 type: 2048
PROVIDER:ip USER:tcp <20+31>
Available bytes:51
4    src:134.48.6.129 dst:192.168.1.6   hlen:20 len:31 tos:0 id:51811 ttl:53 protocol:6 CheckSum:2d02
PROVIDER:tcp USER:raw <20+11>
     src:4660 dst:53205 P  A   s:1 l:11 a:12 w:49680 P 
PROVIDER:raw USER:none <11+-1>
00000000   68 65 6c 6c 6f 20 74 68 65 72 65                 hello there

[0.00036.00315](0.00000.00021)   CAPTURE-00006 54/54
PROVIDER:ether USER:ip <14+40>
Available bytes:54
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:40
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:20 tos:0 id:10553 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <20+0>
     src:53205 dst:4660    A   s:12 l:0 a:12 w:49680 
PROVIDER:raw USER:none <0+-1>


[0.00036.00622](0.00000.00307)   CAPTURE-00007 54/54
PROVIDER:ether USER:ip <14+40>
Available bytes:54
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:40
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:20 tos:0 id:10554 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <20+0>
     src:53205 dst:4660    AF  s:12 l:0 a:12 w:49680 
PROVIDER:raw USER:none <0+-1>


[0.00036.00837](0.00000.00215)   CAPTURE-00008 60/60
PROVIDER:ether USER:ip <14+46>
Available bytes:60
src:00-0f-66-9d-f0-c1 dst:00-14-4f-80-e5-b8 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:46
4    src:134.48.6.129 dst:192.168.1.6   hlen:20 len:20 tos:0 id:51812 ttl:53 protocol:6 CheckSum:2d0c
PROVIDER:tcp USER:raw <20+0>
     src:4660 dst:53205    AF  s:12 l:0 a:12 w:49680 
PROVIDER:raw USER:none <6+-1>
00000000   00 00 29 0d d1 0f                                ..)...

[0.00036.00854](0.00000.00017)   CAPTURE-00009 54/54
PROVIDER:ether USER:ip <14+40>
Available bytes:54
src:00-14-4f-80-e5-b8 dst:00-0f-66-9d-f0-c1 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:40
4    src:192.168.1.6 dst:134.48.6.129   hlen:20 len:20 tos:0 id:10555 ttl:64 protocol:6 CheckSum:0000
PROVIDER:tcp USER:raw <20+0>
     src:53205 dst:4660    A   s:13 l:0 a:13 w:49680 
PROVIDER:raw USER:none <0+-1>


[0.00051.00885](0.00015.00031)   CAPTURE-00010 60/60
PROVIDER:ether USER:ip <14+46>
Available bytes:60
src:00-0f-66-9d-f0-c1 dst:00-14-4f-80-e5-b8 type: 2048
PROVIDER:ip USER:tcp <20+20>
Available bytes:46
4    src:134.48.6.129 dst:192.168.1.6   hlen:20 len:20 tos:0 id:51813 ttl:53 protocol:6 CheckSum:2d0b
PROVIDER:tcp USER:raw <20+0>
     src:4660 dst:53205    A   s:13 l:0 a:13 w:49680 
PROVIDER:raw USER:none <6+-1>
00000000   00 00 ba ea 38 8f                                ....8.