2

I have written a program that sends a tcp request to a web address specified in the command line and prints the response. When I send thisget request to www.google.co.uk (or any website) I get nothing back :(

Could somebody tell me what I'm doing wrong as well as what a correct GET request to google should look like. Here's the code...

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

int main(int argc, char *argv[]){

WSADATA wsaData;
int iResult;

//Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(iResult != 0){
    printf("WSAStartup failed: %d\n", iResult);
    return 1;
}

struct addrinfo *result = NULL,
                *ptr = NULL,
                hints;

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

#define DEFAULT_PORT "80"

//Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if(iResult != 0){
    printf("getaddrinfo failed: %d\n", iResult);
    WSACleanup();
    return 1;
}

SOCKET ConnectSocket = INVALID_SOCKET;

//Attempt to connect to the first address returned by
//the call to getaddrinfo
ptr = result;

//Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
    ptr->ai_protocol);

if(ConnectSocket == INVALID_SOCKET){
    printf("Error at socket(): %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}

//Connect to server
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if(iResult == SOCKET_ERROR){
    closesocket(ConnectSocket);
    ConnectSocket = INVALID_SOCKET;
}

//Should really try the next address returned by getaddrinfo
//if the connect call failed
//But for this simple example we just free the resources
//returned by getaddrinfo and print an error message

freeaddrinfo(result);

if(ConnectSocket == INVALID_SOCKET){
    printf("Unable to connect to server!\n");
    WSACleanup();
    return 1;
}

#define DEFAULT_BUFLEN 512

int recvbuflen = DEFAULT_BUFLEN;

char *sendbuf = "GET /index.html HTTP/1.1\r\n";
char recvbuf[DEFAULT_BUFLEN];

//Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if(iResult == SOCKET_ERROR){
    printf("send failed: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

printf("Bytes Sent: %ld\n", iResult);

//shutdown the connection for sending since no more data will be sent
//the client can still use the ConenctSocket for receiving data
iResult = shutdown(ConnectSocket, SD_SEND);
if(iResult == SOCKET_ERROR){
    printf("shutdown failed: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if(iResult > 0){
        printf("Bytes received: %d\n", iResult);
        printf(recvbuf);
        printf("\n\n");
    } else if(iResult == 0){
        printf("Connection closed\n");
    } else {
        printf("recv failed: %d\n", WSAGetLastError());
    }
} while(iResult > 0);

//cleanup
closesocket(ConnectSocket);
WSACleanup();

return 0;
 }

Thanks in advance.

Nicolas Bachschmidt
  • 6,475
  • 2
  • 26
  • 36
brnby
  • 1,433
  • 1
  • 19
  • 35
  • Have you tried get without a request to the page? I'm just wondering because how do you know if the index page is `index.html` or `index.html` or even `home.html`, etc, etc? So I would try a request like `GET HTTP/1.1`. And why do you close the connection before receiving the answer? – Vite Falcon Jul 10 '12 at 16:15
  • 1
    What does "I get nothing back" mean? You get 0 bytes received, your program freezes or abruptly ends without ever printing anything!? – André Caron Jul 10 '12 at 16:16
  • @ViteFalcon: it doesn't matter. If the URL is invalid, the server would send a proper HTTP response anyways (redirect, page not found, etc.) – André Caron Jul 10 '12 at 16:17

1 Answers1

8

One possible reason is that the server is expecting more data before sending the response.

char *sendbuf = "GET /index.html HTTP/1.1\r\n";

This should proabably be

char *sendbuf = "GET /index.html HTTP/1.1\r\n\r\n";

such that you tell the server not to expect more HTTP headers (each header is followed by a \r\n then an extra \r\n is added to end the request).

Basically, your HTTP request is incomplete. There is at least one more header (Host) that must be provided. Note that the server may (incorrectly) accept and incomplete request anyways. If you want to start simple, copy a request sent by your browser (e.g. open the web debugger and look at the outgoing network requests).

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • 4
    It is going to expect more than that. An HTTP 1.1 request is REQUIRED to include a `Host` header as well, eg: `char *sendbug = "GET /index.html HTTP/1.1\r\nHost: TheServerHostNameHere\r\n\r\n";` – Remy Lebeau Jul 10 '12 at 18:02