cpp はフレームワークなしで HTTP サーバーを書くことができますか?#
何の高級フレームワークも使用せずに、C++ 標準ライブラリといくつかのシステムコールを使用して、シンプルな HTTP リクエストを実装できます。以下は、C++ 標準ライブラリの<iostream>
や<sys/socket.h>
などのヘッダーファイルを使用して、シンプルな HTTP クライアントを作成し、サーバーにリクエストを送信して応答を受信する方法を示す基本的な例です。
例:シンプルな HTTP クライアント#
この例では、生のソケットプログラミングを使用して、HTTP GET リクエストを送信し、サーバーの応答を印刷します。
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
int main() {
// サーバーのアドレスとポート
const char* server = "example.com";
const int port = 80;
// ソケットの作成
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "ソケットの作成エラー" << std::endl;
return 1;
}
// サーバーアドレス構造体
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
// サーバーアドレスの解析
struct hostent* server_info = gethostbyname(server);
if (server_info == nullptr) {
std::cerr << "エラー、ホストが見つかりません" << std::endl;
return 1;
}
// サーバーのIPアドレスをserv_addr構造体にコピー
memcpy(&serv_addr.sin_addr.s_addr, server_info->h_addr, server_info->h_length);
// サーバーに接続
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "サーバーへの接続エラー" << std::endl;
return 1;
}
// HTTP GETリクエストを送信
const char* request = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
if (send(sockfd, request, strlen(request), 0) < 0) {
std::cerr << "リクエスト送信エラー" << std::endl;
return 1;
}
// サーバーの応答を受信
char buffer[4096];
int bytes_received = 0;
while ((bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[bytes_received] = '\0';
std::cout << buffer;
}
if (bytes_received < 0) {
std::cerr << "応答受信エラー" << std::endl;
return 1;
}
// ソケットを閉じる
close(sockfd);
return 0;
}
コードの説明#
-
ソケットの作成:
socket
関数を使用して TCP ソケットを作成します。
-
サーバーアドレス構造体:
sockaddr_in
構造体を使用してサーバーのアドレス情報を格納します。gethostbyname
関数を使用してサーバーのドメイン名を解析します。
-
サーバーに接続:
connect
関数を使用してサーバーに接続します。
-
HTTP リクエストの送信:
- シンプルな HTTP GET リクエスト文字列を構築し、
send
関数を使用してリクエストを送信します。
- シンプルな HTTP GET リクエスト文字列を構築し、
-
サーバーの応答を受信:
recv
関数を使用してサーバーの応答を受信し、それを標準出力に印刷します。
-
ソケットを閉じる:
close
関数を使用してソケットを閉じます。
コンパイルと実行#
上記のコードをhttp_client.cpp
として保存し、g++ を使用してコンパイルして実行します:
g++ -o http_client http_client.cpp
./http_client
注意事項#
- この例はデモ目的のみであり、実際のアプリケーションではタイムアウトやエラーハンドリングなど、より多くのエッジケースを処理する必要があります。
- この例では HTTP 応答のヘッダーと本文の分離を処理していないため、実際のアプリケーションではより複雑な解析ロジックが必要になる場合があります。