Link to home
Start Free TrialLog in
Avatar of BKnet
BKnet

asked on

simple HTTP client use wsock func.

Hi..

I need a client HTTP program use the low level of winsock (Ex :recv , send )). (only for GET file from server)

Use C/C++ code.
thanks.
Avatar of pellep
pellep
Flag of Sweden image

see http://www.faqs.org/rfcs/rfc1945.html for info on the HTTP 1.0 protocol or
http://www.faqs.org/rfcs/rfc2068.html for info on the HTTP 1.1 protocol.

A simple test would be to use TELNET and connect to port 80 on an arbitrary webserver and send GET. You will see the HTML code of the default page of that server flashing by.
Avatar of BKnet
BKnet

ASKER

OK ! I'v read rfc2068 for a week but my program work not well when we merge/split data (gif) file. (it work well for HTML file)
Can you show me a program (source code C++) ?

Thanks.
Why not try Win32 Internet Functions? It should be more easy to implement I guss.

There's a sample about using Internet Functions to reteive a file through HTTP.

http://www.codeproject.com/internet/downloaddlg.asp
Avatar of Paul Maker
i have a MFC exmaple that gets a file from a webserver and displays it at the cmd line ?

also this might help. its a .c file i wote for a web server. now the client type functions such as conenct are missing but things such as pullIn ect will be fine. you just have to write the driver program.. easy

/*
     Written by          :     Paul Maker
     Date               :     01/03/2000

     Description          : socket routines, these are just wrappers around the
                           socket functions
*/

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

int socket_init()
{
     WSADATA wsaData;
     if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)
     {
          printf("WSAStartup failed with error %d\n",WSAGetLastError());
          WSACleanup();
          return 0;
     }
     return 1;
}

int socket_shutdown()
{
     if (WSACleanup() == SOCKET_ERROR)
     {
          printf("WSACleanup failed with error %d\n",WSAGetLastError());
          return 0;
     }
     return 1;
}

SOCKET createSocket()
{
     SOCKET s;
     s = socket(AF_INET, SOCK_STREAM,0);
     if (s == INVALID_SOCKET)
     {
          printf("socket() failed with error %d\n",WSAGetLastError());
          WSACleanup();
     }
     return s;
}

int bindSocket(SOCKET s,int port,char* ip_address)
{
     struct sockaddr_in local;

     local.sin_family = AF_INET;
     local.sin_addr.s_addr = inet_addr(ip_address);
     local.sin_port = htons(port);

     if(bind(s,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR)
     {
          printf("bind() failed with error %d\n",WSAGetLastError());
          WSACleanup();
          return 0;
     }
     return 1;
}

int listenSocket(SOCKET s, int max_connections)
{
     if (listen(s,max_connections) == SOCKET_ERROR)
     {
          printf("listen() failed with error %d\n",WSAGetLastError());
          WSACleanup();
          return 0;
     }
     return 1;
}

int closeSocket(SOCKET s)
{
     if (closesocket(s) == SOCKET_ERROR)
     {
          printf("closesocket() failed with error %d\n",WSAGetLastError());
          WSACleanup();
          return 0;
     }
     return 1;
}

/* rip a whole request in from the client */
char *pullInRequest(SOCKET client)
{
     char *incoming = NULL, *extra = NULL, buffer[2048] = "";
     int size = 0;
     u_long argp;

     /* get the first bit */
     if((size = recv(client,buffer,sizeof(buffer),0)) == SOCKET_ERROR)
     {
          printf("Recive failed on socket ...!\n");
          return NULL;    
     }
     buffer[size] = '\0';
     if((incoming = (char*)malloc(strlen(buffer) + 1)) != NULL)
     {
          strcpy(incoming,buffer);
          if(ioctlsocket(client,FIONREAD,&argp) == SOCKET_ERROR)
          {
               printf("ioctlsocket - check more read failed ...!\n");    
               free(incoming);
               return NULL;
          }
          else
          {
               if(argp > 0)
               {
                    extra = (char*)malloc(argp + 1);
                    if(extra)
                    {
                         if((size = recv(client,extra,_msize(extra),0)) == SOCKET_ERROR)
                         {
                              printf("Recive failed on socket ...!\n");
                              free(incoming);
                              return NULL;    
                         }    
                         incoming = (char*)realloc(incoming, strlen(incoming) + 2 +strlen(extra));
                         if(incoming)
                         {
                              extra[size] = '\0';
                              strcat(incoming,extra);
                              free(extra);
                         }
                         else
                         {
                              printf("malloc failed whilst reciving extra data ...!\n");
                              free(extra);
                              return NULL;
                         }
                    }
                    else
                    {
                         printf("malloc failed for extra revc data buffer ...!\n");
                         free(incoming);
                         return NULL;
                    }
               }
          }
     }
     return incoming;    
}
send and connect can be looked under network and IPC services on VC++

char file[] = "GET /default.html HTTP/1.0"

send(client,file,strlen(file),0);

where client is the client socket you have opened and connected.


The Windows Sockets connect function establishes a connection to a specifed socket.

int connect ( SOCKET s,
 
const struct sockaddr FAR* name,
 
int namelen
 
);
 

ASKER CERTIFIED SOLUTION
Avatar of Paul Maker
Paul Maker
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I have provided a more structured example of retrieving a file from a web server.

The engine code has been split into re-usable functions. You will need to link to ws2_32.lib.

Hope this helps !!


/**
**
**Author:
**  Saurabh Dasgupta
**
**Date:
**    May 17,2000
**
**/

#include    <winsock2.h>
#include    <windows.h>
#include    <stdio.h>

#define _WSOCK_VER_ 0x0202


void ShowUsage();
BOOLEAN ProcessCmdLineArgs(int argc, char **argv, char *lpszHost, char *lpszFile);
int __stdcall Connect(const char *lpszHost,
                      int iPort,
                      SOCKET *sSock,
                      unsigned char *uchIP,
                      int iTiOut);

int __stdcall ReadCompleteData(
                               SOCKET s,
                               unsigned char *lpsBuffer,
                               int nSize);


int __stdcall SendCompleteData(
                               SOCKET s,
                               unsigned char *lpsBuffer,
                               int nSize);


long _stdcall DataAvailable(
                                long nSock ,
                                long *pBytes);


void main(int argc, char **argv)
    {
    char lpszHost[1024]="";
    char lpszFile[1024]="";
    char lpszRequestString[1024]="";
    char lpszBuffer[1024*20]="";

    if (
        ProcessCmdLineArgs(argc, argv,lpszHost,lpszFile) == FALSE)
        {
        fprintf(stderr,"\nInvalid arguments!!");
        ShowUsage();
        exit(1);
        }

    //make a socket connection to the server
    SOCKET s;
    int nError=0;
    unsigned char ucIpaddr[4];
    nError = Connect(lpszHost,80,&s,&ucIpaddr[0],0);

    //build the request string, this will be transmitted to the server
    wsprintf(lpszRequestString,"GET %s\r\n\0.9",lpszFile);

    //transmit the request string
    SendCompleteData(
                    s,
                    (unsigned char*)lpszRequestString,
                    lstrlen(lpszRequestString));

    int nActualBytesRead=0;
    nActualBytesRead = ReadCompleteData ( s,(unsigned char*)lpszBuffer,sizeof(lpszBuffer));

    //check for error
    if (nActualBytesRead <= 0)
        {
        fprintf(stderr,"\nError occurred while reading (%d) ",nActualBytesRead);
        exit(1);
        }
       
    //display all the data to the stdout
    int k=0;
    for (k = 0; k<nActualBytesRead;k++)
        {
        fprintf(stdout,"%c",(char)lpszBuffer[k]);
        }
    }

BOOLEAN ProcessCmdLineArgs(int argc, char **argv, char *lpszHost, char *lpszFile)
    {
    if (argc != 3)
        return FALSE;
    else
        {
        strcpy(lpszHost,argv[1]);
        strcpy(lpszFile,argv[2]);
        return TRUE;
        }
    }

void ShowUsage()
    {
    char lpszFile[512]="/business/faq.htm";
    char lpszSrvr[512]="coolsrvr";

    fprintf(stderr,"\nHttpClie [remote_host] [file_name]\n");
    fprintf(stderr,"\nExample:");
    fprintf(stderr,"\nHttpClie %s  %s",lpszSrvr,lpszFile);
    fprintf(stderr,"\nWill display the contents of  %s retrieved from %s in the stdout",lpszFile,lpszSrvr);
    }

int __stdcall Connect(const char *lpszHost,
                      int iPort,
                      SOCKET *sSock,
                      unsigned char *uchIP,
                      int iTiOut)
      {
    /*
    Inputs:
        iPort:port on the remote server to which you would like to connect
        pSock:pointer to a socket
        uchIP:a pointer to the first element of an array of 'unsigned char',
        this will take the resolved IP address back to the caller.
        iTiOut:specify time out interval if any.

    Description:
        Tries to establish a socket connection to the remote host lpszHost,
    at the port iPort. On success a valid socket descriptor is returned.
    The array uchIp mut be atleast 4 bytes in size, so as to be able to
    accomodate all the 4 bytes of the IP address that will be resolved from the
    host name lpszHost.
    Error:
        On error , the error code obtained from WSAGetLastError() is returned.
    */
      
      //SOCKET VARIABLES
    //the verion of WinSock library depends on the macro  _WSOCK_VER_
       WORD    WINSOCK_VERSION      =_WSOCK_VER_;

    //if user has specified a port number then use that else use the
    //one defined by PORT_NO
    const int PORT_NO = 80;
    int port_no=PORT_NO;
    if (0!=iPort) port_no = iPort;

      WSADATA             wsadata;                              //FOR RETRIEVING STARTUP WINSOCK IMPLEMENTATION INFO
      int                        _error;
      LPHOSTENT             lphostent;            
      SOCKADDR_IN       sockaddr_sock;
      int                        nconnect;
      SOCKET                   nsocket;
      if (WSAStartup(WINSOCK_VERSION,&wsadata))
            {
            //FAILURE HAS OCCURRED, EXIT WITH GRACE
            return(WSAGetLastError());                               
            }
      else
            {
            //GET THE IP ADDRESS OF THE HOST
            lphostent=gethostbyname(lpszHost);
            if (lphostent==NULL)                                          //ERROR HAS OCCURRED IN RETRIEVING HOST IP ADDR
                  {
                  _error=WSAGetLastError();
                  WSACleanup();                                          //CLEAN UP SOCKETS
                  return(_error);
                  }
            else
                  {
            //extract the IP addr in dotted decimal format
            struct in_addr addr_tmp=*((LPIN_ADDR)*lphostent->h_addr_list);
            if (uchIP != NULL )
                {
                uchIP[0]=addr_tmp.S_un.S_un_b.s_b1;
                uchIP[1]=addr_tmp.S_un.S_un_b.s_b2;
                uchIP[2]=addr_tmp.S_un.S_un_b.s_b3;
                uchIP[3]=addr_tmp.S_un.S_un_b.s_b4;
                }
                  nsocket=socket(PF_INET,SOCK_STREAM,0);
                  if (nsocket==INVALID_SOCKET)
                        {
                        //SOCKET CREATION FAILED
                        WSACleanup();                                          //CLEAN UP SOCKETS
                        _error=WSAGetLastError();
                        return(_error);                                     //IF SOCKET  NOT CREATED THEN EXIT THREAD
                        }
                  else
                        {
                        //SOCKET CREATION WAS A SUCCESS, CREATE A CONNECTION
                         sockaddr_sock.sin_family=AF_INET;
                        sockaddr_sock.sin_port=htons(port_no);
                        sockaddr_sock.sin_addr=*((LPIN_ADDR)*lphostent->h_addr_list);
                        nconnect=connect(nsocket,(struct sockaddr*)&sockaddr_sock,sizeof(SOCKADDR_IN));
                        if (nconnect!=0)
                              {
                              _error=WSAGetLastError();
                              return(_error);
                              }
                        else
                              {
                              //CONNECTION WAS A SUCESS, RETURN ZERO
                              *sSock=nsocket;
                              return(0);
                              }
                        }
                  }
            }
      }



int __stdcall ReadCompleteData(
                               SOCKET s,
                               unsigned char *lpsBuffer,
                               int nSize)
      {
    /**
    Inputs:
        SOCKET s:a valid socket descriptor
        unsigned char *lpsBuffer:a valid memory buffer for taking back all the data
        int nSize:the maximum number of bytes that are to be read. This should not
        be more than the capacity of the lpsBuffer memory region.

    Description:
          This function will read from socket s all n bytes and then return.
      it keeps iterating till the
        1)entire n bytes has been read or
        2)there is some error condition.
        3)there are no more bytes to be read, i.e the total no of bytes read
        in this case will be less than nSize
      If succes then n else SOCKET_ERROR

    Return:
        If there was no error, then the total no of bytes that were read are
    returned. If there was an error, then WSAGetLastError is returned.
    **/
    long  bytes_available=0;
      int bytes_read=0;
      int bytes_toberead=0;
      int stat=0;
      while(bytes_read < nSize)
            {
            stat=0;
            bytes_toberead=nSize - bytes_read;
       
            stat=recv(s,(char*)(lpsBuffer + bytes_read), bytes_toberead,0);
            if (stat == SOCKET_ERROR)
            {
            /**
            if error in reading then SOCKET_ERROR ,then return the error code
            **/
                  return stat;    
            }

        if (stat == 0)
            {
            /**
            if connection was closed            
            gracefully from the other side then return the total bytes read, and exit from function here
            **/
            return bytes_read;
            }
            else
                  bytes_read= bytes_read + stat;
            }
      return bytes_read;
      }


int __stdcall SendCompleteData(SOCKET s,unsigned char *lpsBuffer,int nSize)
      {
      int nsend=0;
      int bytes_sent=0;
      int bytes_remain=0;
      while(bytes_sent < nSize)
            {
            bytes_remain=nSize -  bytes_sent;
            nsend = send(s,      (char*) (lpsBuffer + bytes_sent), bytes_remain,0);
            if (nsend == SOCKET_ERROR)
                  return SOCKET_ERROR;
            else
                  bytes_sent+=nsend;
            }
      return bytes_sent;
      }


long _stdcall DataAvailable(long nSock , long *pBytes)
    {
    /**
    Queries a TCP socket to know the number of bytes that are available for
    immediate reading. If success then 0 else error code.
    **/
    long read_query=0;
    unsigned long nDataAvailable=0;
    *pBytes=0;

    read_query=ioctlsocket(nSock,(long)FIONREAD,&nDataAvailable);
    if (0== read_query)
        {
        *pBytes=(long)nDataAvailable;
        return 0;
        }
    else
        {
        return  WSAGetLastError();
        }

    }