LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   HTTP Keep-Alive socket problem (https://www.linuxquestions.org/questions/programming-9/http-keep-alive-socket-problem-631305/)

imdupeng 03-28-2008 12:39 PM

HTTP Keep-Alive socket problem
 
Hello everyone, I am a newbie in UNIX/Linux socket programming. This is a class project that I had trouble with.

==================================================

I was trying to make “Keep-Alive” HTTP connections to the server in a tiny web crawler project. Here is the problem: when I tried to recv() the first page, it succeeded. However, the 2nd consecutive recv() will receive zero bytes, for which I really have no idea. I did put a “Keep-Alive” field in the request message when I called send().

I don't quite know how to implement HTTP persistent connection by using Keep-Alive. I extracted the socket-related code into a small program as attached.

Would you please take a look at the code and explain what was wrong with it to me? That would be of great help since I have stuck on this problem for days.

By the way, the program was compiled under SunOS using g++ and -lsocket.
==================================================

Code:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <string>
#include <iostream>

using namespace std;

// ------------------------------------------------------
const short SOCKET_ERROR = -1;

const short RECV_BUFFER_SIZE = 20;
const short REQUEST_BUFFER_SIZE = 255;

int sock;
char recv_buf [RECV_BUFFER_SIZE + 1];
char req_buf [REQUEST_BUFFER_SIZE + 1];

const static char REQUEST_TEMPLATE [] =
{
        "GET %s HTTP/1.1\r\n"
        "Host: xxx.xxx.xxx\r\n" // should be replaced with a really host
        "Connection: Keep-Alive\r\n"
        "\r\n"
};

// ------------------------------------------------------
void create_socket ();
void download (const string& path, string& response);

// ------------------------------------------------------

int main (void)
{
        string first_addr = "/~pdu/index.html"; // should be replaced with a really URL
        string second_addr = "/~pdu/a.html"; // should be replaced with a really URL
        string response;

        create_socket ();
        download (first_addr, response);
        cout << response << endl << endl;
        response = "";
        download (second_addr, response);
        if (response.size() > 0)
        {
                cout << response << endl;
        }
        else
        {
                cout << "### The 2nd recv() failed to receive any bytes from the socket!" << endl << endl;
        }
       
        close (sock);

        return 0;
}

void create_socket ()
{
        struct sockaddr_in addr;

        // ------------------------------------------------------
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sock == SOCKET_ERROR)
    {
        perror ("Could not make a socket.\n");
                exit (-1);
    }

        cout << ">>> Socket created!" << endl;

        // ------------------------------------------------------
        struct hostent* host_info = gethostbyname("cse.unl.edu");       
       
        cout << ">>> DNS done!" << endl;

        long host_addr;

        /* copy address into long */
        memcpy(&host_addr, host_info->h_addr,
                host_info->h_length);

        /* fill address struct */
        addr.sin_addr.s_addr = host_addr;
        addr.sin_port = htons(80);
        addr.sin_family = AF_INET;

        // ------------------------------------------------------
        if( connect(sock, (struct sockaddr*)(&addr),
                sizeof(addr)) == SOCKET_ERROR )
    {
        perror("Could not connect to HTTP server.\n");
                exit (-1);
    }

        cout << ">>> Connection established!" << endl;
}

void download (const string& path, string& response)
{
        size_t nBytes = snprintf(
                req_buf,
                REQUEST_BUFFER_SIZE,
                REQUEST_TEMPLATE,
                path.c_str());

        if (nBytes >= REQUEST_BUFFER_SIZE)
        {
        cerr << "Buffer is too small for making a request message" << endl;
                exit (-1);
        }

        if (send(sock, req_buf, nBytes, 0) != nBytes)
        {
        perror("Could not send request to the HTTP server.\n");
                exit (-1);
        }
        cout << ">>> Request sent! -> " << path << endl << req_buf << endl;
       
        ssize_t size = 0;
       
        while ((size = recv(sock, recv_buf,
                RECV_BUFFER_SIZE, 0)) > 0)
        {
                recv_buf[size] = '\0';
                response.append(recv_buf);
    }

        cout << ">>> Response received!" << endl;
}

Thank you!

imdupeng 03-29-2008 11:17 AM

Come on guys, please help! Thx!


All times are GMT -5. The time now is 10:39 AM.