Let’s Build a Web Server. Part 1
ruslanspivak.com
ruslanspivak.com
#include <WinSock.h>
#include <stdio.h>
#pragma comment(lib, "wsock32.lib")
int main(int argc, const char *argv[]) {
WSADATA wsadata;
WSAStartup(2, &wsadata);
sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("0.0.0.0");
address.sin_port = htons(80);
int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(sock, (struct sockaddr *)&address, sizeof(address));
for(;;) {
listen(sock, 0);
int connection = accept(sock, NULL, NULL);
char recvBuffer[1024];
int recvSize = recv(connection, recvBuffer, sizeof(recvBuffer)-1, 0);
recvBuffer[recvSize]=0;
printf(recvBuffer);
char response[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\nlol";
send(connection, response, sizeof(response), 0);
closesocket(connection);
}
return 0;
}isnt it better to write that as:
const char* response = "HTTP/1.1 200 OK\nContent-Type: text/html\n\nlol"; ?
Having the string in a writable buffer when you have no intention of modifying the string seems like not a very good idea.
Any decent compiler will evaluate "strlen(response)" at compile time and hence there will be no run time penalty here.
Any decent compiler will also notice this and put the string literal in the .RODATA section. Using "const" doesn't really make a difference, it's more of a hint for the compiler.
It really doesn't make any difference in this case.
[1] Where future developers includes me - I'll forget what I wrote in six months or less.
[0] http://stackoverflow.com/questions/2288856/when-implementing...
I haven't read the whole thing but I like this bit:
> There are many algorithms that are best written using an exit from the middle of a loop. If not written in this fashion, techniques such as the traditional “priming” of a loop must be used. For example, in reading a file:
read(a, b, c)
WHILE NOT eof DO
{ process a, b, & c }
read(a, b, c)
END WHILE
LOOP
read(a, b, c)
WHEN eof EXIT
{ process a, b, & c }
END LOOP
> The example on the left [top] shows the priming of a loop. This requires duplication of the READ statement or, in other cases, creation of a subprogram to eliminate the duplication, both of which are undesirable. As well, loop priming can be done an arbitrary distance before the beginning of the loop making the program difficult to read as the priming statement(s) is critical to the understanding of the loop.GET / HTTP/1.0
is perfectly valid.
This is just an advert for his book anyway.
Also, keep in mind that the author is working on a book on the subject, and this is most likely an excerpt, or at least a highly condensed version of what the books shows. Hopefully, the book would be a lot more detailed. (Furthermore, if you have written a web server before or are a long time Apache contributor or something like that, you are not the target audience.)
That being said, if I had never done any network programming before, I would probably still be slightly confused at the end, because I would not know anything about the socket API. As I have done network programming before, I found myself getting kind of bored quickly. And the really interesting stuff you'd need know for writing a realy web server is not even touched in this part ("Part 1" kind of implies there will be at least one more part) - how do you map URLs to replies? How do you send files or call code dynamically to generate responses (a simple CGI implementation might be interesting for study purposes)? How do you handle multiple concurrent requests?