SOCKETS PROGRAMING FOR WINDOWS 95

From Web (09.06.1997)

Table of Contents

1. Preamble

This page is in Pre Alpha. That means no grammer checks, no editting and speeling mistakes galore! The explanations and the final version will come soon. Check it out at your own risk!

2. Socket programming for Windows 95

Have you ever been locked up in a room? all alone, no one to speak to, no one to flirt with. Such a life would be miserable! The desktop computers used to live under similar conditions before the arrival of the Internet. The Internet usurped in a new era into the life of the computer. Now the PC could venture outside the confines of the desktop and communicate with any computer in the world. The cuckoo had crooned, the age of networking had finally arrived. Computers world wide were finally 'talking' to each other.

Before a computer can starts talking I first has to check whether someone is listening at the other end. This negotiation is called 'establishing a connection'. On a multitasking operating system like Windows'95 we can establish more than one connection at a time. So for every connection we want to establish we have to create a new socket. A Socket is our interface to the networking world. A Socket is used whenever we have to communicate over a network. The WinSock is the Windows version of the Socket interface and is made up of a number of functions. These functions make it easier for us to communicate by hiding the underlying layers and their complexities from us. It is usually through a Socket that machines communicate on a network.

Since we don't have to worry about the network layers below us, all we need to know are some of the details of IP like the IP address and what Transport layer protocol we want, e.g. TCP, UDP etc.

Sockets programming consists of calling functions from a DLL with the required number of parameters. To jump into the pond of socket programming we should be equipped with some basic knowledge of it. Read on to find all you need.

When you need to talk to any other computer, you need a telephone line and an Internet service provider. When you call someone up and say "Hello", what you expect is a reply. But if you don't get one then you can't do anything except hang up. If you get a reply then you can start the conversation. This is the set of rules (called a protocol) that we must follow.

We'll be writing extremely simple and dirty windows programs and then snapping on the WinSock code. If you don't know C under Windows, then you might finds things a wee bit difficult. These programs have no error check, but that's the way we like 'em.

2.1. The smallest windows program we could make

If you see the program given below (if you are an experienced VC++ programmer, you must have already guessed it ), its nothing but the smallest windows program we could make. It creates a window with a title a1 and when we click in the window, it displays a message box.

Note:-To run this program, first create a project in Visual C++ ( We're using Visual C++ 4.0 ) and insert file a1.cpp into the project a1. Add wsock32.dll to the project. Now build the project.

\*----------------------------------------------------------------
Step #1
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
   FILE *fp=fopen("c:\\z.txt","a+");
   fprintf(fp,"%s\n",p);
   fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
   {
     MessageBox(0,"end","end",0);
   }
   if ( x == WM_DESTROY)
     PostQuitMessage(0);
   return DefWindowProc(w,x,y,z);
 }

We have initialized the member lpfnWndProc with the name of the function we want to associate with window a1. The function zzz is the function we want to call when ever anything happens to the window a1 (e.g. maximize, close, left click etc.). This function is called the callback function. The program uses the callback function zzz to show us a messagebox whenever user clicks in the window.

2.2. Our first step towards winsock programing

Our next step is our first step towards winsock programing. Go ahead, run the program and find out what it does.

\*----------------------------------------------------------------
Step #2
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];char bb[20000];
 WSADATA ws;DWORD e;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {
      e=WSAStartup(0x0101,&ws);
                 sprintf(aa,"e..%ld",e);
                 MessageBox(0,aa,aa,0);
                 abc(aa);
      MessageBox(0,"end","end",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

The only line we've added in the code is WSAStartup(0x0101,&ws). This function takes the version number of the winsock as the first parameter. It is 1.1 in our case. The second parameter is the address of the structure WSADATA. The function WSAStartup() will fill all the members of the structure ws.

2.3. List out all the members of the structure

We list out all the members of the structure with their respective values in the following programe. When you run the following program, check the file z.txt in your root directory.

\*----------------------------------------------------------------
Step #3
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];char bb[20000];
 WSADATA ws;DWORD e;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {   abc("Before WSAStartup");
             sprintf(aa,"wVersion....%d",ws.wVersion);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"wHighVersion....%d",ws.wHighVersion);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"szDescription....%s",&ws.szDescription);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"szSystemStatus....%s",&ws.szSystemStatus);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"iMaxSockets....%u",ws.iMaxSockets);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"iMaxUdpDg....%u",ws.iMaxUdpDg);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"lpVendorInfo....%s",ws.lpVendorInfo);
             MessageBox(0,aa,aa,0);
             abc(aa);

             e=WSAStartup(0x0101,&ws);

             sprintf(aa,"e..%ld",e);
             MessageBox(0,aa,aa,0);
             abc("After WSAStartup");
             sprintf(aa,"wVersion....%d",ws.wVersion);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"wHighVersion....%d",ws.wHighVersion);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"szDescription....%s",&ws.szDescription);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"szSystemStatus....%s",&ws.szSystemStatus);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"iMaxSockets....%u",ws.iMaxSockets);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"iMaxUdpDg....%u",ws.iMaxUdpDg);
             MessageBox(0,aa,aa,0);
             abc(aa);
             sprintf(aa,"lpVendorInfo....%s",ws.lpVendorInfo);
             MessageBox(0,aa,aa,0);
             abc(aa);
             MessageBox(0,"end","end",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

Now that we know what our first winsock function does. Remember to include it always, or you won't get far.

2.4. Create a socket

The next thing we have to do is create a socket. A socket is just a number which represent certain parameters. We use the function socket() to create one.

\*----------------------------------------------------------------
Step #4
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];SOCKET s;
 WSADATA ws;DWORD e;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {
                 e=WSAStartup(0x0101,&ws);
                 sprintf(aa,"e=%ld",e);
      abc(aa);
                 s=socket(PF_INET,SOCK_DGRAM,0);
                 sprintf(aa,"s=%ld",s);
                 abc(aa);
                 MessageBox(0,aa,aa,0);
                 MessageBox(0,"end","end",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

The variable s is called a socket which is going to be used on the Internet ( because we've said PF_INET) and which will use UDP (SOCK_DGRAM) as its protocol of choice. We'll need s, the handle to our socket for most of the other functions.

2.5. IP address

When using sockets over the Internet, we have to remember the IP address of the computer we wish to link to. An IP address is a four byte number which is read and written byte by byte, i.e. 202.54.1.18 is the IP of our ISP. Each number is a byte which comes together to form a larger number. This was done to ease the recall of IP addresses and is called the Dotted Decimal Format. Computers don't understand this format and so we have to use the function inet_addr() to convert them. The actual process is simple. What the function inet_addr() does is this (140*2^24)+(252*2^16)+ (1*2^8) +(32*2^1). It returns a long number.

Run the following programe and check the result.

\*----------------------------------------------------------------
Step #5
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];
 WSADATA ws;DWORD e;long dd;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {
                 dd = inet_addr("140.252.1.32");
                sprintf(aa,"dd=%ld",dd);
                abc(aa);
                MessageBox(0,aa,aa,0);
                MessageBox(0,"end","end",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

2.6. Convert a long number into a dotted decimal notation

As we can convert a dotted decimal to a long number, we can also convert a long number into a dotted decimal notation. inet_ntoa() is the function which enables us to do the same.

\*----------------------------------------------------------------
Step #6
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];
 WSADATA ws;DWORD e;long dd;struct in_addr sa;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {
                 sa.s_addr = inet_addr("140.252.1.32");
                 sprintf(aa,"sa.s_addr=%ld",sa.s_addr);
                 abc(aa);
                 MessageBox(0,aa,aa,0);
                 char *p=inet_ntoa(sa);
                 sprintf(aa,"p=%s",p);
                 MessageBox(0,aa,aa,0);
                 MessageBox(0,"hi","hi",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

2.7. Motorola & Intel chips stored numbers differently

The problem with the Internet was how to connect different types of computers from around the world. There are so many incompatible makes around like Apple, Intel PC, large mainframes and so on and so forth. It's rather difficult to make a Macintosh talk to an Intel machine since they both store their numbers differently. To over come this problem, called the little endian / big endian or NUXI problem, the Internet community standardized on the big endian way of storing numbers. Since the Intel chips stored numbers differently, we used the function htons to do the conversion.

\*----------------------------------------------------------------
Step #7
a1.cpp
------------------------------------------------------------------*\
 #include <windows.h>
 #include <stdio.h>
 void abc(char *p)
 {
         FILE *fp=fopen("c:\\z.txt","a+");
         fprintf(fp,"%s\n",p);
         fclose(fp);
 }
 WNDCLASS a;HWND b;MSG c;char aa[200];SOCKET s;
 WSADATA ws;DWORD e;long ii;
 long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
 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)
         {
                 ii=htons(2);
                 sprintf(aa,"ii.htons(2)=..%ld",ii);
                 abc(aa);
                 MessageBox(0,aa,aa,0);
                 ii=htons(512);
                 sprintf(aa,"ii.htons(512)=..%ld",ii);
                 abc(aa);
                 MessageBox(0,aa,aa,0);
                 MessageBox(0,"end","end",0);
         }
         if ( x == WM_DESTROY)
                 PostQuitMessage(0);
         return DefWindowProc(w,x,y,z);
 }

This program show us how we solve the problem using the function htons(). This is the function which enables us to convert a little endian number to big endian number.

All the important concepts about sockets have just been explained to you. Read the next part of the tutorial to find out more...


Vijay Mukhi's Computer Institute
VMCI, B-13, Everest Building, Tardeo, Bombay 400 034, India
E-mail:vmukhi@giasbm01.vsnl.net.in Tel : 91-22-496 4335 /6/7/8/9 Fax : 91-22-307 28 59
http://www.neca.com/~vmis