C++ Winsock Basic HTTP Connection


I had some unix socket code that I was working with, and I needed to convert it to run on windows. Thanks to a handy Windows Socket PDF, I was able to get some basic code going.

This is not meant to be 'production' level stuff... merely a hello world of using winsock. One of the things I did not account for in this code was download lag. For instance, if you are downloading a 40kb page it may take a few seconds. What happens is the recv() function can only access data that has already been downloaded, so this code will end an http download 'early' if the download is anything slower than instant.
#include <iostream>
#include <string>
 
#include <stdlib.h>
#include <winsock.h>//dont forget to add wsock32.lib to linker dependencies
 
using namespace std;
 
#define BUFFERSIZE 1024
void die_with_error(char *errorMessage);
void die_with_wserror(char *errorMessage);
 
int main(int argc, char *argv[])
{
    string request;
    string response;
    int resp_leng;
 
    char buffer[BUFFERSIZE];
    struct sockaddr_in serveraddr;
    int sock;
 
    WSADATA wsaData;
    char *ipaddress = "208.109.181.178";
    int port = 80;
 
    request+="GET /test.html HTTP/1.0\r\n";
    request+="Host: www.zedwood.com\r\n";
    request+="\r\n";
 
    //init winsock
    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
        die_with_wserror("WSAStartup() failed");
 
    //open socket
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        die_with_wserror("socket() failed");
 
    //connect
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family      = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(ipaddress);
    serveraddr.sin_port        = htons((unsigned short) port);
    if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
        die_with_wserror("connect() failed");
 
    //send request
    if (send(sock, request.c_str(), request.length(), 0) != request.length())
        die_with_wserror("send() sent a different number of bytes than expected");
 
    //get response
    response = "";
    resp_leng= BUFFERSIZE;
    while (resp_leng == BUFFERSIZE)
    {
        resp_leng= recv(sock, (char*)&buffer, BUFFERSIZE, 0);
        if (resp_leng>0)
            response+= string(buffer).substr(0,resp_leng);
        //note: download lag is not handled in this code
    }
 
    //display response
    cout << response << endl;
 
    //disconnect
    closesocket(sock);
 
    //cleanup
    WSACleanup();
    return 0;
}
 
void die_with_error(char *errorMessage)
{
    cerr << errorMessage << endl;
    exit(1);
}
 
void die_with_wserror(char *errorMessage)
{
    cerr << errorMessage << ": " << WSAGetLastError() << endl;
    exit(1);
}

code snippets are licensed under Creative Commons CC-By-SA 3.0 (unless otherwise specified)

Digital Picture Frames on 2011-07-14 03:33:21
I find this article from google, it’s really useful for me, hope I can post this in my blog. nice post , I will share with my friends: )

daniel on 2011-08-02 11:44:08
What if the amount of bytes returned is exactly the size of the buffer? Wouldn't recv block? (That's what happens to me)

nefton on 2013-11-01 22:28:09
thanx

DWW on 2016-07-30 17:27:21
This is crazy man! <h1>Wow</h1>

Dev on 2016-08-07 14:12:36
Instead of adding wsock32.lib to build dependencies just do:
#pragma comment(lib,"wsock32")