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.
#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 = '\0';
response.append(recv_buf);
}
cout << ">>> Response received!" << endl;
}
Thank you!