I am learning tutorials online about http client programming using Linux. I found these 2 sample programs, but I am kind of confused on what command line arguments are suppose to be passed to it.

I think for program 1, string [1] should be the IP address of the url, and string [2] should be the user designed output file to store the contents of the url. Is that correct?

for program 2, I am clueless on what command line arguments we are suppose to pass to it.
Does program 2 download the contents of the webpage into another file?

/* http-client.c
 *
 * Copyright (c) 2000 Sean Walton and Macmillan Publishers.  Use may be in
 * whole or in part in accordance to the General Public License (GPL).
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
*/

/*****************************************************************************/
/*** http-client.c                                                         ***/
/***                                                                       ***/
/*** This program shows what the HTTP server sends to the client.  First,  ***/
/*** it opens a TCP socket to the server.  Then, it sends the request      ***/
/*** "GET <resource> HTTP/1.0\n\n" (the second newline is needed for the   ***/
/*** "message-end" message.  Lastly it prints out the reply.               ***/
/*****************************************************************************/

#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <errno.h>

#define MAXBUF  1024
void PANIC(char *msg);
#define PANIC(msg)  {perror(msg); abort();}

int main(int Count, char *Strings[])
{   int sockfd, bytes_read;
    struct sockaddr_in dest;
    char buffer[MAXBUF];

    /*---Make sure we have the right number of parameters---*/
    if ( Count != 3 )
        PANIC("usage: testport <IP-addr> <send-msg>\n");
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        PANIC("Socket");

    /*---Initialize server address/port struct---*/
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(80); /*default HTTP Server port */
    if ( inet_addr(Strings[1], &dest.sin_addr.s_addr) == 0 )
        PANIC(Strings[1]);

    /*---Connect to server---*/
    if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 )
        PANIC("Connect");

    sprintf(buffer, "GET %s HTTP/1.0\n\n", Strings[2]);
    send(sockfd, buffer, strlen(buffer), 0);

    /*---While there's data, read and print it---*/
    do
    {
        bzero(buffer, sizeof(buffer));
        bytes_read = recv(sockfd, buffer, sizeof(buffer), 0);
        if ( bytes_read > 0 )
            printf("%s", buffer);
    }
    while ( bytes_read > 0 );

    /*---Clean up---*/
    close(sockfd);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
 
#define PORT ((u_short)80)
#define BUFFER_SIZE 256
#define REQ_SIZE 60
 
int main(int argc, char *argv[]){
  int sock,i;                  
  int rc;
  struct hostent *servhost;  
  struct sockaddr_in server; 
  char *hostname ="www.isaa.me"; 
  char *path = "/index.html";
  char request[REQ_SIZE] = "GET ";
   
char buffer[BUFFER_SIZE];
  FILE *fin, *stdout;
    i = 1;
    if(argc > 1){
        while(i < argc){
            if (!strcmp(argv[i], "-f")){
                stdout = fopen(argv[i+1], "w");
                if(stdout == NULL){ perror("Check output file!"); exit(1);}
            }
            if (!strcmp(argv[i], "-u")){
                hostname = argv[i+1];
            }
            if(!strcmp(argv[i], "-p")){
                path = argv[i+1];
            }
            i++;
        }
    }else{
        stdout = stdout;
    }
     
    strcat(request, path);
    strcat(request, " HTTP/1.0\n\n");
 
  servhost = gethostbyname(hostname);
  if (servhost == NULL) {
    fprintf(stderr, "%s unknown host\n", hostname);
    exit(2);
  }
   
  memset(&server, 0, sizeof(server));
 
  server.sin_family = AF_INET;
   
 
  memcpy(&server.sin_addr, servhost->h_addr, servhost->h_length);
 
  server.sin_port = htons(PORT);
 
  sock = socket(AF_INET, SOCK_STREAM, 0);
     
  if (sock < 0) {
    perror("opening stream socket");
    exit(1);
  }
   
  if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
    perror("connecting stream socket");
    exit(1);
  }
 
     
    rc = 0;
    rc = write(sock, request, strlen(request)+1);
    if(rc<0) 
    {   
        perror("cannot send data ");
        close(sock);
        exit(1);  
    }
 
     
    fin = fdopen(sock, "r");
    rc = 0;
    while(1){
        if (fgets (buffer, sizeof(buffer), fin) == NULL) break; 
        if (!strcmp (buffer, "\r\n")) rc = 1;
        if(rc == 1) fprintf (stdout, "%s", buffer);       
    }
    fclose(fin);
    if(stdout != stdout) fclose(stdout);
     
  close(sock);
}

That's some-funny looking code in the first program. It looks like one programmer wrote a "test port" program and a second one expanded it into a http client.
In the header, it looks like we're using an http client with a single parameter.

/*** "GET <resource> HTTP/1.0\n\n" (the second newline is needed for the   ***/

However, right here it looks like we're sending a random meaningless string to a server.

/*---Make sure we have the right number of parameters---*/
    if ( Count != 3 )
        PANIC("usage: testport <IP-addr> <send-msg>\n");

However, what's really going on is we're grabbing a web page from a server by using it's IP address.
Here we grab the IP address (NOT A HOSTNAME) from "Strings" the command line arguments.

if ( inet_addr(Strings[1], &dest.sin_addr.s_addr) == 0 )

And here we tell the server which file we want on the server

sprintf(buffer, "GET %s HTTP/1.0\n\n", Strings[2]);

The full usage looks like this:

GET <xxx.xxx.xxx.xxx> </path/to/file.html>

To get /index.html from a web service on the same machine, you'd use:

GET 127.0.0.1 /index.html

Notice the space between the IP address and the file name!


Now to the second program.

Let's look at this block:

if (!strcmp(argv[i], "-f")){
                stdout = fopen(argv[i+1], "w");
                if(stdout == NULL){ perror("Check output file!"); exit(1);}
            }
            if (!strcmp(argv[i], "-u")){
                hostname = argv[i+1];
            }
            if(!strcmp(argv[i], "-p")){
                path = argv[i+1];
            }

Looking at this code it looks like your command line arguments go like this:

./program [-f <outPutFile>] [-u <hostname>] [-p <pathOnRemoteMachine>]

So if you wanted to get www.google.com/index.html and write it to google.html on your machine, you would use:

./program -f google.html -u www.google.com -p /index.html

Hope that helps!

Happy coding!

This article has been dead for over six months. Start a new discussion instead.