Topic : Socket Programming
Author : Vijay Mukhi
Page : << Previous 7  Next >>
Go to page :

stack also matches the header against the data and makes sure that the packet hasn't been altered or damaged during transit. If all is well, the 20 bytes of the IP header and the 20 bytes of the TCP header are removed ( Remember, the IP header is on the outside, the TCP on the inside ) and the data sent off to the waiting receive statement. The TCP/IP stack is the file Wsock32.dll in C:\Window\System. Not only does the stack strip off headers, it also adds them when data is sent across the Internet from your machine.

In actuality, 'TCP/IP stack' is just another name for the WinSock.

An HTTP Server

#include <windows.h>
#include <winsock.h>
#include <stdio.h>
void abc(char *p)
{       FILE *fp=fopen("z.txt","a+");
WNDCLASS a;HWND b;MSG c;char aa[200];char bb[20000];
long _stdcall zzz (HWND,UINT,WPARAM,LPARAM);
int _stdcall WinMain(HINSTANCE i,HINSTANCE j,char *k,int l)
        while ( GetMessage(&c,0,0,0) )
        return 1;
WSADATA ws;SOCKET s,s1,s2;sockaddr_in A,A1;int d,d1=200;
long _stdcall zzz (HWND w,UINT x,WPARAM y,LPARAM z)
        if ( x == WM_USER+1)
        if ( LOWORD(z)&FD_ACCEPT == FD_ACCEPT)
            s1=accept(s,(struct sockaddr *) &A1,&d);
            sprintf(aa,"accept s1 %ld",s1);
        if(LOWORD(z)&FD_READ == FD_READ)
            sprintf(aa,"recv %ld",d);
            strcpy(aa,"HTTP/1.0 200 OK\r\n" );
            strcat(aa,"Date: Sunday Sun, 21 Oct 1995 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: Sunday Sun, 21 Oct 1995 19:38:46          GMT\r\n");
            strcat(aa,"Content-length: 1000\r\n\r\n");
            sprintf(aa,"send %ld",d);
        if ( x == WM_LBUTTONDOWN)
                sprintf(aa,"WSAStartup %ld",d);
                s=socket(AF_INET, SOCK_STREAM,0);
                sprintf(aa,"socket %ld",s);
                A.sin_port = htons(80);
                A.sin_addr.s_addr =INADDR_ANY;
                d=bind(s,(struct sockaddr *) &A,sizeof(A));
                sprintf(aa,"bind %ld",d);
                sprintf(aa,"listen %ld",d);
        if ( x == WM_DESTROY)
        return DefWindowProc(w,x,y,z);

An HTTP server is a little different from a Time Server because now we have to handle TCP/IP rather than UDP/IP. The key difference between TCP/IP and UDP is that UDP is not a connection oriented protocol. In other words, it doesn't form a permanent (and virtual) link with the computer at the other end. TCP does, so you can treat a TCP connection in the same way you'd treat reading data from a file on the Hard Disk Drive.

It's because you, as the server, have to form a connection with the client that this server's a little more complex than the Time Server.

Read through the code and then jump directly to the if (x == WM_LBUTTONDOWN) part of it. That's the portion that is called when you click in the window. Most of the code is the same as always, but you'll start seeing the changes by the time you reach the ninth line. The line A.sin_addr.s_addr=INADDR_ANY; should be familiar to you from the Time Server and it doesn't need much explaining anyway. The Bind() function too has been explained before. It's the WSAAsyncSelect() that we have to tackle here.

WSAAsyncSelect() is a function which helps implement some sort of multitasking under Windows95. It's first parameter is s, the handle to the socket. B is another handle, this time a handle to the window, WM_USER+1 will take some explaining. WM_USER+1 is the message WSAAsyncSelect is supposed to call whenever anything happens to the socket. It's the same thing as the function zzz being called everytime something significant happens to the window. WM_USER is a macro which represents the number 1024. All message calls from 0 to 1023 have been reservered by Microsoft for itself.

The fourth parameter holds the number of the socket attributes to be made non-blocking i.e. the message WM_USER+1 should be called for the specified events. Here we've specified that WM_USER+1 should be called for every read and accept. When we make a function non-blocking, it means that the program will no longer wait for the function to end before it proceeds. If we hadn't used WSAAsyncSelect() then we'd have to place a recv() right here, an act which would halt program execution till someone connected to our site. By making the function non-blocking we make sure that recv() is only called when there's data ready for it in the buffer.

The next function is listen() which is passed the handle to the socket and the maximum length of the queue.

When someone connects to the server and his connection is accepted, WM_USER+1 is called. In WM_USER+1 we examine the LOWORD of z to discover the reason we've been called. If we've been called because of an Accept then one IF statement is executed and if we've been called for a Read, then another IF statement is called.

Since we're first called for an Accept, the function accept(), which is passed the handle to the socket, the address of the structure &A and the address of the variable d (which is a int), is called. The structure A will hold information about the person attempting to connect to us.

If on the other hand, we've been called because someone has sent us data, the code in the other IF statement is executed. There we first use recv() to collect all we've been

Page : << Previous 7  Next >>