社内ISUCONに参加してから、HTTPなWebサーバを1から作ってみたいなと思ったので、試してみました。
環境構築
install gcc
1 2 3 4 |
$ sudo yum install gcc $ gcc gcc: fatal error: no input files compilation terminated. |
サンプルコードの作成
1 2 3 4 5 6 7 |
#include <stdio.h> int main() { printf("hello world\n"); return 0; } |
実行
1 2 3 4 5 |
$ gcc sample.c $ ls a.out sample.c $ ./a.out hello world |
実行できました。ビルド環境が構築できてますね。
このままでは開発がしんどかったので、EclipseとCDTを入れました。
以下、サイトのサンプルを見て実装、Chromeでアクセスした時にLengthの値が一致していないとエラーになったので、Contents-Lengthの値だけ修正しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> int main() { int sock0; struct sockaddr_in addr; struct sockaddr_in client; int len; int sock; int yes = 1; char buf[2048]; char inbuf[2048]; sock0 = socket(AF_INET, SOCK_STREAM, 0); if (sock0 < 0) { perror("socket"); return 1; } addr.sin_family = AF_INET; addr.sin_port = htons(9000); addr.sin_addr.s_addr = INADDR_ANY; setsockopt(sock0, SOL_SOCKET, SO_REUSEADDR, (const char *) &yes, sizeof(yes)); if (bind(sock0, (struct sockaddr *) &addr, sizeof(addr)) != 0) { perror("bind"); return 1; } if (listen(sock0, 5) != 0) { perror("listen"); return 1; } memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n" "Date: Sun, 26 Feb 2017 15:13:00 GMT\r\n" "Server: Apache/2.2.31 (Amazon)\r\n" "Last-Modified: Sun, 26 Feb 2017 15:06:20 GMT\r\n" "Accept-Ranges: bytes\r\n" "Content-Length: 6\r\n" "Connection: close\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "\r\n" "HELLO\r\n"); while (1) { len = sizeof(client); sock = accept(sock0, (struct sockaddr *) &client, &len); if (sock < 0) { perror("accept"); break; } memset(inbuf, 0, sizeof(inbuf)); recv(sock, inbuf, sizeof(inbuf), 0); send(sock, buf, (int) strlen(buf), 0); close(sock); } close(sock0); return 0; } |
Chromeでアクセスすると応答が返ってきました。
次に、Apacheの静的コンテンツと自作HTTPサーバのどちらが応答速度が早いかを競って見ます。
実行環境
環境はAWSのEC2でt2.nanoインスタンスを立ち上げました。インスタンスにはApacheを入れて、HELLO文字列を返すだけの静的コンテンツを用意します。
1 |
$ sudo yum install httpd |
Apacheの応答を確認して、自作HTTPサーバの応答もまったく同じ状態にします。
1 2 3 4 5 6 7 8 |
HTTP/1.1 200 OK Date: Sun, 26 Feb 2017 15:13:00 GMT Server: Apache/2.2.31 (Amazon) Last-Modified: Sun, 26 Feb 2017 15:06:20 GMT Accept-Ranges: bytes Content-Length: 6 Connection: close Content-Type: text/html; charset=UTF-8 |
速度比較
10回ほど試行してみました。
Apache(単位はミリ秒)
1 2 3 4 5 6 7 8 9 10 11 12 |
74 57 50 43 50 52 59 49 44 50 -- ave: 52.8 |
自作(単位はミリ秒)
1 2 3 4 5 6 7 8 9 10 11 12 |
57 48 59 82 38 43 45 45 46 45 -- ave: 50.8 |
自作が早いとはいえ、ほとんど誤差の範囲ですね。もう少し大きいファイルや簡単な動的スクリプトを使っての比較も今後試して見ます。次の社内ISUCONで使えるレベルまで持って行きたい。。
参考
Linuxネットワークプログラミングhttp://www.geekpage.jp/programming/linux-network/