Conversation
Satorien
commented
Jan 1, 2026
- READMEに記載の仕様に基づいて実装
There was a problem hiding this comment.
Pull request overview
This PR implements a basic TCP socket-based server-client communication system in C. The server listens on port 8080 and handles arithmetic calculation requests via a /calc HTTP endpoint, while the client sends calculation queries and displays responses.
Key changes:
- Utility functions for socket initialization, error handling, and logging
- Server implementation with signal handling for graceful shutdown and request processing
- Client implementation with command-line argument support for sending calculation requests
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| utils.h | Declares utility functions for socket operations, error handling, and logging |
| utils.c | Implements utility functions for socket initialization, cleanup, error handling, and logging |
| server.c | Implements TCP server with HTTP-like request handling for arithmetic calculations |
| client.c | Implements TCP client that connects to server and sends calculation requests |
| Makefile | Build configuration for compiling server and client executables |
| .gitignore | Ignores compiled executables with run_* pattern |
Critical Issues Found:
- Multiple memory leaks in both server and client code
- Missing error checking on read/write operations
- Incorrect Content-Length in HTTP responses
- Security vulnerabilities including buffer overflow risks and unvalidated input
- Inappropriate error handling that terminates the server on malformed requests
- Signal handler with incorrect function signature
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
変更は不要と判断したため、PRはクローズしました |
akmhmgc
left a comment
There was a problem hiding this comment.
全体的に読みやすかったです!
不正な入力などの細かい対応は今後されると思うのでコメントはしていません。
| void connect_client_to_server(int client_socket_fd) { | ||
| // サーバアドレス構造体 | ||
| struct sockaddr_in server_address; | ||
| int domain = (strcmp(IP_VERSION, "IPv6") == 0) ? AF_INET6 : AF_INET; |
There was a problem hiding this comment.
address familyなので変数名はdomainではなくaddress_family等が良いと思いました。
| while (sent_len < request_len) { | ||
| ssize_t n = write(client_socket_fd, request + sent_len, request_len - sent_len); | ||
| if (n < 0) { | ||
| handle_error("Write to server failed"); | ||
| } | ||
| sent_len += n; | ||
| } |
There was a problem hiding this comment.
short count対策しているのが良いと思いました!
(nits) サーバー側でも同様の処理をしているのでラッパー関数を書いても良いかもしれません。
| void close_socket(int socket_fd) { | ||
| // ソケットのクローズ | ||
| if (close(socket_fd) < 0) { | ||
| handle_error("Close failed"); | ||
| } | ||
| } No newline at end of file |
| size_t sent_len = 0; | ||
| while (sent_len < request_len) { | ||
| ssize_t n = write(client_socket_fd, request + sent_len, request_len - sent_len); | ||
| if (n < 0) { |
There was a problem hiding this comment.
EINTRはハンドラの処理が終わった後復帰する可能性があるのでリトライしても良いかもしれません。
| size_t request_len = strlen(request); | ||
| size_t sent_len = 0; | ||
| while (sent_len < request_len) { | ||
| ssize_t n = write(client_socket_fd, request + sent_len, request_len - sent_len); |
There was a problem hiding this comment.
今だとサーバーのソケットが閉じている時にこのループでwriteが二回以上呼び出されると、SIGPIPEを受け取ってクライアントのプロセスが落ちると思います。
SIGPIPEを無視するにはwriteではなくてflagを利用できるsendを利用すると良いです。
ref: https://linuxjm.sourceforge.io/html/LDP_man-pages/man2/send.2.html
| void handle_client_request(int client_socket_fd) { | ||
| // リクエストの処理 | ||
| char *buffer = calloc(BUFFER_SIZE, 1); | ||
| ssize_t bytes_read = read(client_socket_fd, buffer, BUFFER_SIZE - 1); |
There was a problem hiding this comment.
writeと同様readもshort countの可能性があるのでループして要求した文字数分読めたかチェックした方が良さそうです。
| char *buffer = calloc(BUFFER_SIZE, 1); | ||
| ssize_t bytes_read = read(client_socket_fd, buffer, BUFFER_SIZE - 1); | ||
| if (bytes_read < 0) { | ||
| log_msg("Read from client failed\n"); |
| // アドレスの再利用を有効化 | ||
| int optval = 1; | ||
| if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { | ||
| log_msg("setsockopt SO_REUSEADDR failed"); |
There was a problem hiding this comment.
エラーを見る限り致命的なものしかないので、ここで失敗した場合は処理を終了した方が良い気がします。
https://linuxjm.sourceforge.io/html/LDP_man-pages/man2/setsockopt.2.html
| } | ||
|
|
||
| // リクエストの受信と処理 | ||
| while (is_server_running) { |
There was a problem hiding this comment.
シグナルハンドラでフラグを変更してgraceful shutdownに対応しているは良いですね。参考になりました。
| size_t response_len = strlen(response); | ||
| size_t sent_len = 0; | ||
| while (sent_len < response_len) { | ||
| ssize_t n = write(client_socket_fd, response + sent_len, response_len - sent_len); |
There was a problem hiding this comment.
https://github.com/Satorien/Socket-Programming/pull/1/changes#r2658611560
と同様にクライアントがソケットを閉じた後にwriteが呼び出されるとサーバーがクラッシュするのでsendでオプションを渡すのが良いと思います。