SOCKETS PROGRAMING FOR WINDOWS 95
From Web (09.06.1997)
Table of Contents
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!
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.
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.
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.
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.
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.
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);
}
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);
}
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