LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 03-28-2008, 01:39 PM   #1
imdupeng
LQ Newbie
 
Registered: Mar 2008
Posts: 2

Rep: Reputation: 0
Unhappy 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!

Last edited by imdupeng; 03-28-2008 at 02:16 PM.
 
Old 03-29-2008, 12:17 PM   #2
imdupeng
LQ Newbie
 
Registered: Mar 2008
Posts: 2

Original Poster
Rep: Reputation: 0
Come on guys, please help! Thx!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
PHP - Check if Socket is alive baddah Programming 6 12-11-2007 09:50 AM
XDMCP - problem keeping sessions alive RedHatCat Linux - Networking 2 06-27-2007 04:05 AM
Set Up a Service to Send Apache HTTP 2.2 Reporter Log to a Socket nkanthikiran Red Hat 0 11-03-2006 12:07 AM
Unable to connect to UNIX socket /tmp/.esd/socket error while using grip dr_zayus69 Linux - Software 4 08-23-2005 08:28 PM
http, socket and tcp/ip comparison gogo Linux - Networking 5 10-05-2002 02:57 AM


All times are GMT -5. The time now is 04:45 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration