C++ - Simple server which sends simple HTML to clients
Question
Now, I'm just fooling around with this and I'm not sure as to why this isn't working.
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <cassert>
const char html[] = "HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-type: text/html\r\n"
"\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Hello, world!</title>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Hello, world!</h1>\r\n"
"</body>\r\n"
"</html>\r\n\r\n";
int main() {
WSADATA wsa;
assert( WSAStartup( MAKEWORD( 2, 2 ), &wsa ) == 0 );
addrinfo *res = NULL;
addrinfo hints;
ZeroMemory( &hints, sizeof( hints ) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
assert( getaddrinfo( NULL, "80", &hints, &res ) == 0 );
SOCKET s = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
assert( s != INVALID_SOCKET );
assert( bind( s, res->ai_addr, (int)res->ai_addrlen ) != SOCKET_ERROR );
assert( listen( s, SOMAXCONN ) != SOCKET_ERROR );
SOCKET client = accept( s, NULL, NULL );
assert( client != INVALID_SOCKET );
char buffer[512];
int bytes;
bytes = recv( client, buffer, 512, 0 );
for ( int i = 0; i < bytes; ++i ) {
std::cout << buffer[i];
}
assert( send( client, html, strlen( html ) - 1, 0 ) > 0 );
assert( shutdown( client, SD_BOTH ) != SOCKET_ERROR );
closesocket( client );
WSACleanup();
return 0;
}
When I compile and run this and then navigate to 127.0.0.1 in my browser I get this in my console:
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (K HTML, like Gecko) Chrome/2.0.172.8 Safari/530.5
Cache-Control: max-age=0
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,/;q=0.5
Accept-Encoding: gzip,deflate,bzip2,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
EDIT - I've updated the HTML I'm sending. I just tested this with Mozilla Firefox and Google Chrome and it works in Firefox, but not Chrome!
EDIT 2 - So it seems that the reason it was working on Firefox, but not Chrome, was because Firefox displays the HTML as its received, while Chrome waits for the connection to close before doing any rendering. I added the code to close the socket and it worked. I've updated my code with the working source.
Solution
You need to send back the status line:
HTTP/1.1 200 OK
preceding your response headers.
See Fiddler (www.fiddler2.com) to get a better idea of what proper HTTP responses look like.
Regarding your later edit, all browsers wait for a certain amount of data before starting rendering; Chrome's limit is different than Firefox's. If you had set a Content-Length or used HTTP Chunked encoding, you would have seen proper behavior.
OTHER TIPS
Look at Mongoose http://code.google.com/p/mongoose/ It's a self contained library that's a multithreaded http web server and has a super simple api (yet complete). Within a few minutes I was able to bind it to my already existing app.
I had the same question earlier today (to give my C++ application a web end) Giving C++ Application a HTTP Web Server Functionality