C++でHTTPサーバー作った
はじめに
C++を使ってHTTPサーバーを作成しました。ソケットを使ったプログラムは書いたことはありましたが、しっかりと理解していなかったため勉強になりました。正しいHTTPの規約には則っていないかもしれませんが、ブラウザアプリやHTTP用のクラスが動いたので十分としています。
WSL上で開発をしています。また、C++はあまり使ったことがないとこから始めてました。
あんまり技術的なことには触れません。
実装したもの
ソケットの管理
基本的にサーバー側のソケットはcreate、bindが終わった後はループさせる中でlisten, accept, recvを繰り替えすだけです。
また、複数のポートなどで通信を受け取れるようにselectを使用しました。
設定ファイルの読み込み
設定ファイルを読み取れるようにし、
IP、ポート
サーバー名
locationの設定
デフォルトエラーページ
許容する最大のコンテンツサイズ
オートインデックスの許可
ディレクトリのルート
許可するメソッド(GET,POST,DELETEのみ実装)
リダイレクト
デフォルトのページ
ファイルアップロード
CGIの設定
を設定できるようにしました。
CGIってなんや
用意されたプログラムを呼び出し、指定されたファイルの中身を入力とし、その出力を返すようにする仕組みです。
ここの実行のためにはプロセスを生成し、パイプを使って標準入力や標準出力を扱えるようにする必要がありました。使いかたを完全に忘れていました。
動作中の画像
よく分からなかったこと
ブラウザアプリとの1セッションが終わったあと、謎の接続が2~4回ほど発生しました。ブラウザの動き的には完全にセッションが終わったあとに繋がれていたため、keep-aliveとは違うような・・・。
この場合、相手側から何も送信されずrecv関数で動作が止まってしまうため、ソケットをノンブロッキングに変更しました。
新しく使ってみたもの
VSCodeの拡張
AI assistant for software developers | Tabnine
限定的なタイミングで使えるようなことがありました。
めちゃめちゃ便利ってほどではなかったかも・・・?
例を挙げると、
列挙型のそれぞれに関して動作をif分岐させる場合、2つ目以降はifを書いたあたりで1行分予測してくれました。
また、ファイルが読み取れなかった場合に出すエラー文(あくまでデバッグ用)なども1行分予測してくれました。
予測されるタイミングを覚えてきたらさらに便利になりそうでした。
テスト用
google/googletest: GoogleTest - Google Testing and Mocking Framework (github.com)
C++で関数のテストを行うために使用しました。主に単体テストで使用しましたが、フレンドクラスを宣言することでプライベートメソッドの単体テストも可能でした。特に設定ファイルの読み取りではテストが楽になりました。
ただやっぱり後半は単体でテストするのも面倒になってました(笑)
unittest — Unit testing framework — Python 3.11.2 documentation
HTTPを使ったテストではこちらを使用しました。@classmethod を使うことで特定の設定ファイルでサーバーを立ち上げ、その設定ファイル用のテストを回すこともできました。
時間管理用
Toggl: Time Tracking Software, Project Planning & Hiring Tools
このプログラムの作成にかけた時間が気になるのと、大体週にどの程度時間がさけているかを知ろうと思い使ってみました。
タイマーを止め忘れることは何度かありましたが大体1時間単位で記録できたので良しとしました。
終わってみて
C++を使うことがほとんどないため、逐一ググりながら書いてました。後からもっとC++っぽい書き方が出てきたりしました・・・。
仕様はあまり確認せず、とにかく手を動かすことから始めたのであまりきれいなクラス分けなどはしませんでした。ちゃんと考えて書きたい反面ちゃんとHTTPの仕様を読むのもどこまで確認すればいいのか、って感じでとりあえず始めてました。どっかで考えるような勉強をしたいです。
まとめ
作業時間 93時間