Conversation
|
クライアントとサーバーで共通の問題は片方にしかコメントしていません。 |
common_utils.h
Outdated
| #define BUFFER_SIZE 1024 | ||
| #define LOOPBACK_ADDRESS "127.0.0.1" | ||
|
|
||
| void cleanup(int socket_fd) |
There was a problem hiding this comment.
ヘッダファイルにはプロトタイプ宣言だけを書いて、関数の実装は .c ファイルに書くのが一般的です。
.h は複数のファイルから include されるのが想定されます。
すると、実装が複数個作られることになり、リンクの際にどれを使えばよいかわからなくなりエラーになります。
There was a problem hiding this comment.
ご指摘ありがとうございます。理解しました。
同ファイルの関数はプロトタイプ宣言にし、実装を common_utils.c に記述するように修正しました。合わせて、実行コマンドが複雑になってきたので Makefile を作成しました: 9730d44
|
|
||
| ## その他気になったことメモ | ||
|
|
||
| - C では try catch で囲んでエラーが発生したら stack trace を出す、みたいなのは出来ないのだろうか? |
There was a problem hiding this comment.
C には例外機能は無いですが、(スタックの特定の構造を前提とした)バックトレースを取得する機能については、標準外ですが、 glibc 関数としてあったりはします。
https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
client.c
Outdated
| { | ||
| struct sockaddr_in socket_address; | ||
| socket_address.sin_family = AF_INET; | ||
| socket_address.sin_addr.s_addr = inet_addr(LOOPBACK_ADDRESS); |
client.c
Outdated
| if (connect(socket_fd, (struct sockaddr *)&socket_address, sizeof(socket_address)) == -1) | ||
| { | ||
| perror("connect failed"); | ||
| cleanup(socket_fd); |
There was a problem hiding this comment.
cleanup, exit のコピペを減らすにはどういう構造にするとよいでしょうか?
There was a problem hiding this comment.
共通処理を何かしらの手段にひとつにまとめ、各所から呼び出すようにするのはどうかと考えました。
こちらでは関数にしています: dfa7ac9
There was a problem hiding this comment.
メモ: goto を使うのもよくやるらしい (このようになにかのリソースを開放するような使い方が唯一許されている goto ぐらいの例)
There was a problem hiding this comment.
メモ: system call がどのような挙動をしたか等で処理を分けたくなった場合はさらに工夫が必要
client.c
Outdated
| } | ||
| else if (bytes_written < request_length) | ||
| { | ||
| fprintf(stderr, "Partial write occurred\n"); |
There was a problem hiding this comment.
一部分しか write できなかったのは、失敗ではなく、想定内の挙動です。(書き込み先のネットワークのバッファが足りなかった。書き込みの途中で割り込みを受けて一部完了で復帰した、など。)
その際にも正しく処理を続けられるコードにしてみてください。
There was a problem hiding this comment.
manも確認しておくと良いですね。
https://man7.org/linux/man-pages/man2/write.2.html
The number of bytes written may be less than count if, for
example, there is insufficient space on the underlying physical
medium, or the RLIMIT_FSIZE resource limit is encountered (see
setrlimit(2)), or the call was interrupted by a signal handler
after having written less than count bytes. (See also pipe(7).)
There was a problem hiding this comment.
hayashi-ay さん、ドキュメントもありがとうございます。
client.c
Outdated
|
|
||
| printf("Sent HTTP GET request\n"); | ||
|
|
||
| bytes_read = read(socket_fd, buffer, BUFFER_SIZE - 1); |
There was a problem hiding this comment.
read も一回で全部のデータが読めるとは限りません。
(データが複数パケットに分かれて、一つ目だけ到着した場合はどうなる?)
また、受け取ったデータ全体が buffer のサイズより大きいケースも考えてください。
There was a problem hiding this comment.
こちらも同様に。
https://man7.org/linux/man-pages/man2/read.2.html
It is not an error if this number is smaller than the number of
bytes requested; this may happen for example because fewer bytes
are actually available right now (maybe because we were close to
end-of-file, or because we are reading from a pipe, or from a
terminal), or because read() was interrupted by a signal.
server.c
Outdated
| cleanup(socket_fd); | ||
| exit(EXIT_FAILURE); | ||
| } | ||
| if (listen(socket_fd, 3) == -1) |
There was a problem hiding this comment.
特に深い理由はなく、ちょっと負荷を与えたらすぐに許容できなくなる程度の値にしていました。
このままでいいのかについてはスレッド導入時に再検討する予定でいますので、その旨コメントに残しておきます: 51de367
There was a problem hiding this comment.
まあ決めの問題かなとは思います。3というのが意味がありそうな値だったのと、第2引数がなにか把握されているか確認してみたくらいです。
server.c
Outdated
| } | ||
|
|
||
| cleanup(socket_fd); | ||
| return 0; |
There was a problem hiding this comment.
ご指摘ありがとうございます。 global constants を把握出来ておりませんでした。こちら使うよう修正しました。
https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170
There was a problem hiding this comment.
良いと思います。まあ好みではあると思いますが、自分が見たときの断面ではエラー時にはEXIT_FAILUREを使っていたのが気になったのでコメントしたくらいです。
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <arpa/inet.h> | ||
| #include <errno.h> | ||
| #include "common_utils.h" |
There was a problem hiding this comment.
何らかの規則性を持たせたい
- alphabet 順
- 独自定義のファイル等と標準ライブラリの間に一行空ける
- etc.
| total_read += bytes_read; | ||
| if (strstr(buffer, "\r\n\r\n") != NULL) // ボディのない GET リクエストのみが来る想定 | ||
| { | ||
| break; | ||
| } |
There was a problem hiding this comment.
keep-alive が来た時に変になる?
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Keep-Alive
| socket_address.sin6_port = htons(atoi(PORT)); | ||
|
|
||
| char buffer[BUFFER_SIZE] = {0}; | ||
| char *http_request = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"; |
|
|
||
| printf("Sent HTTP GET request\n"); | ||
|
|
||
| ssize_t total_received = receive_response(socket_fd, response, MAX_MESSAGE_SIZE - 1); |
There was a problem hiding this comment.
意味的には、
MAX_MESSAGE_SIZE = BUFFER_SIZE - 1
として MAX_MESSAGE_SIZE を渡すようにする?
レビューができるようサーバー課題の実装をプルリクエストにしています。