.
carbonize.co.ukcarbonize.co.uk

Y!Tunnel
Trillian
YahELite
Opera
Ad Aware
Ultraedit
YahSEek

Advertisements:


Send honey to your loved ones

[Get Opera!]

Synfire's Guide to C Programming
12. Sockets

    Well, now you've got what it takes to write some fairly kewl programs that work with files on your computer, and can ease many common tasks. BUT WAIT! What about working across networks, and creating some kewl client server programs? Well, if you've ever used a chat program or web browser you might have thought what it would be like to create your own. That is what this section is about. This is called 'Socket Programming' and I think this is the best part of programming. ( Of course this is comming from a hacker ;) )

    Okay, lets jump into this. First thing you should do is login as root and go to the '/usr/include/sys' directory. Then open the 'socket.h' file in your favorite text editor. Now scroll down to where you see...
struct osockaddr
{
   unsigned short int sa_family;
   unsigned char sa_data[14];
};
    Now this is kinda cryptic, so lets create another struct. Just below the osockaddr struct type this:
struct SockAddr
{
  short int Family;
  unsigned short int Port;
  struct in_addr Address;
  unsigned char Zero[8];
};
   Now that you have both of these structs socket programming is fairly simple. Now there are many tutorials on socket programming so I'm just going over one aspect. Here we will write a Simple TCP Stream client and server. This is enough to get the general idea, and write fairly good programs, TCP Stream programs are the most created on the net because it is the most reliable method of data transfer.

tcpclient.c
-------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* Yes there are allot of header files but you will need them all! */

#define PORT 6666 /* This will be the port that your client will
		     connect to on the remote machine. If this
		     client wants to connect to Telnet then you
		     would use port 23, FTP port 21, and the list
		     goes on, make sure if you write a server then
		     you make the ports in the 4 digit range so
		     not to interfer with other network programs. */

#define MAXDATASIZE 100 /* This is the maximum size of information
			   that can be recieved at a time from the
			   server. */

int main(int argc, char *argv[])
{
	int sock_fd, numbytes;
	/* Creates a socket file descriptor for data exchange,
	   numbytes holds the number of bytes recieved from
	   the server. */

	char buffer[MAXDATASIZE];
	/* This holds all the information sent from the server. */

	struct hostent *he;
	/* This structure is used to get the IP address from a hostname. */

	struct SockAdder Their;
	/* This is the structure you created to hold information
	   about the stream you will be using. */

	if(argc != 2)
	{
		/* This checks to make sure that the right
		   amount of arguements were passed on the
		   command line. */

		fprintf(stderr, "usage: client hostname\n";
		exit (1);
	}

	if((he=gethostbyname(argv[1])) == NULL)
	{
		herror("gethostbyname");
		exit (1);
	}
	

	/* socket() -
	   This is always the first part of a connection.
	   You will notice that the connections will be built by if
	   statements. The above if statement should be used if you
	   think the user might type in a domain name like...
	   "www.yahoo.com" instead of an IP address. Then to create
	   an internet connection using the TCP protocol type this
	   next if statement. */

	if((sock_fd=socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		perror("socket");
		exit (1);
	}

	/*
	This is the information that will be used to make a connection.
	just leave it like this everytime, I do it this way to make it
	more readable. */

	Their.Family = AF_INET;
	/* This is the socket address family, This text only covers
	AF_INET connections so if you want more info type 'man socket'
	at your linux prompt. */

	Their.Port = htons(PORT);
	/* This is the port your client will be connecting to. For the
	   most part this will always be the same. Just always remember to
	   define your port at the beginning of your program. Or if you want
	   a user specified port you could use...

	   unsigned int PORT = argv[3];

	   just after main(). */

	Their.Address = *((struct in_addr *)he->h_addr);
	/* This is the address of the person your connecting to
	   for the most part this will stay the same too. */

	bzero(&(Their.Zero), 8);
	/* Don't ask just add it here everytime! */


	if(connect(sock_fd, (struct sockaddr *)&Their, sizeof(struct sockaddr)) == -1)
	{
	/* This creates a full 'handshake' connection to
	   the remote host. ALL CLIENT PROGRAMS WILL HAVE THIS! */

		perror("connect");
		exit (1);
	}

	if((numbytes=recv(sock_fd,buffer,MAXDATASIZE,0)) == -1)
	{
		/* I will explain this a bit. recv() gets information
	 	   from the server through your file descriptor(sock_fd)
		   and places as much as it can, determined by MAXDATASIZE,
		   into 'buffer'. Then the number of bytes placed into
		   'buffer' is placed into 'numbytes'. */

		perror("recv");
		exit (1);
	}

	buffer[numbytes] = '\0';
	/* A lacking carrage return is placed at the end of the buffer. */

	printf("> %s", buffer);
	/* prints all information in the buffer to the screen. */

	close(sock_fd);
	/* closes the connection */

	return (0);
}
-------------------------------------------------
        Now I have commented this enought that you should be able to figure it out on your own. I do recomend reading a guide on Networking to better understand the lingo, but other than that you should do fine.

        Here we go, the client program is VERY easy but a bit more goes into server programs. Servers have to bind to a port, recieve connection, fork off a sub-proccess and handle sending and recieving data. I know it sounds like alot but I'm sure you'll have no problems following the comments. In this section I will OverComment for you! ;)

tcpserver.c
-------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
/* Yes, even more includes but once again you'll need them all! */

#define PORT 6666
/* This is the port the server will be listening on. */

#define BACKLOG 10
/* This is how many connections your server will accept at once. */


int main()
{
	int sock_fd, new_fd;
	/* Two file discriptors are created. Servers have to have
	   both. One will be used for when your server forks to the
	   client. */

	struct SockAddr My;
	struct SockAddr Their;
	/* Creates a local socket and a remote socket. The remote
	   socket holds the person connectings information and the
       	   local one holds your servers connection information. */

	int Size;
	/* This will hold the size of SockAddr for use with accept(). */

	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		/* creates your local socket, just like in the client */

		perror("socket");
		exit (1);
	}

	My.Family = AF_INET;
	My.Port = htons(PORT);
	/* The above two set up your SA_family and your local port
	   just as in the client. */

	My.Address.s_addr = INADDR_ANY;
	/* This sets the address to your current IP. For servers
	   this is what you always want. */
	
	bzero(&(My.Zero), 8);
	/* Once again, don't ask just do it. ;) */

	if (bind(sock_fd, (struct sockaddr *)&My, sizeof(struct sockaddr)) == -1)
	{
		/* This binds your server to your local port.
		   This will keep other programs from trying 
		   to use the same port. */

		perror("bind");
		exit (1);
	}

	if (listen(sock_fd, BACKLOG) == -1)
	{
		/* This statement tells your computer to sit and
		   wait and listen for up to 10, the amount of 
		   BACKLOG, connections. */

		perror("listen");
		exit(1);
	}

	while (1) 
	{
		/* while(1) is called a forever loop, meaning that
		   it will just loop over constantly until return()
		   is called with an int. */

		Size = sizeof(struct SockAddr);
		/* Stores the size of struct SockAddr to Size for
		   use with accept. */

		if ((new_fd = accept(sock_fd, (struct sockaddr *)&Their, &Size)) -1)
		{
		/* The above is called when a connection 
		   is made, it uses your other file descriptor
		   'new_fd' to recieve their socket information. */

		perror("accept");
		printf("> %s has connected!\n", inet_ntoa(Their.Address));
		/* Prints the IP address of the connecting person on the 
		   screen. Thats about all you get on the server side.
		   This is good if you want to get someones IP for some
		   reason ;) just create this client and have the connect
		   to you on the 'PORT' port and it will display their 
		   IP on screen. */


		 if (!fork())
		 {
			 /* Don't worry about that just use it.
			    I'm the kinda person that if you always
			    have to do it, then I'm not gonna take
			    time to explain it. Just do it. */

			 if(send(new_fd, "Hello Client!\n", 14, 0) == -1) 
			{
				/* sends the string Hello Client! to
				   the client. For more advance servers
				   you would put a function there and 
				   have all the operations placed in the
				   function. */

				perror("send");
			}
			close(new_fd);
			/* This closes the file descriptor. */
			exit(0);
		}
		close(new_fd);

		while(waitpid(-1,NULL,WNOHANG) > 0);
		/* Once again just do it. */
	}
}
------------------------------------

        Okay that is enough for this tutorial. If you really want to get serious about C socket programming for linux go to...

http://www.programmersheaven.com/
or
http://www.google.com/linux?q=Socket+Programming&hl=en

        I forgot to tell you. Most of the stuff in this tutorial will work for you Windows Programmers, except for the Socket Programming. Windows have their own Socket API and I suggest looking for information at...

http://www.google.com/microsoft?q=Socket+Programming&hl=en

        for more information. Well I hate to say it, but this is all I'm doing on C. I know it's not the best tutorial in the world, but it does get you started. After all I'm more or less a C++ coder but there is the occasional job the C is need. I by no means think C++ is better than C, it's just my preferred language, I mean ASM is much better than C or C++ but there is no way in HELL I would write all my programs in it! So for now I'm out, LaTeRz!


Back to top | Contact me