
mixi にてやねうらおさんから http://x68000.q-e-d.net/~68user/net/c-http-1.html のコードについてご指摘を受けたので、ここで書いても伝わるかどうかわかりませんが、一応回答と言い訳を。
> connectに失敗したときにソケットがcloseされない。
うーん。懐かしの malloc/free 論争を思い出してしまいました。その考えを否定はしませんが、わたしはここでは close しません。サンプルコードの可読性を損なうから。実務であっても、即終了するなら close しないと思う。理由は「OS にまかせて実害がないから」。常駐モノならするけど。
> そのreadってhttpで送られてきたデータを受け取っているのでないの?
> データ自体はRFCで規定されている長さまでなら送られてくると思うのだけど。
わたしの知る限りでは、RFC2616 においては HTTP のレスポンスメッセージの最大長は規定されていませんので、理論的には ssize_t の範囲のデータが返ってくると思います (実際は mbuf がもたなくてブロックしてしまうでしょうが)。
ついでに恥をさらしておくと、あのソースは他にもいろいろまずいところがあって、サンプルコードであるという前提であったとしても、以下の問題点があります。参考になれば>葵さん
◎直すべきもの
・write(2) のエラーチェックが漏れている。
・read(2) のエラーチェックが漏れている。
・close(2) のエラーチェックが漏れている。
・おっしゃるとおり、int は ssize_t に直すべき。
ところで負け惜しみのようでかっこ悪いですが、「ssize_t は unsigned」というのは
誤りだと思います (signed じゃないと read(2) が -1 を返せない)。ちなみに FreeBSD
では int でした。
◎直した方がいいなぁと思うもの
・socket(2)・connect(2) などのエラーチェックで、errno を表示した方が親切。
・gethostbyname(3) のエラーチェックは herror(3) あたりを使った方が親切。
・read(s, buf, BUF_LEN) は read(s, buf, sizeof(buf)) に変えたいなぁ。
・strcmp(argv[1], "http://" ) は strcmp(argv[1], "http://" ) != 0 としたい。
・socket(AF_INET, ...) は socket(PF_INET, ...) が正しい (プロトコルファミリの指定なので)
・write(2) で全データを送りきったかどうかのチェックが漏れている。
(ただし、送りきれない場合があるよってのはページをわけて説明したい)
・BUF_LEN は定数の種類を増やすとわかりにくくなると思っていたのですが、
今考えると分けておいた方がいいような気がしてきました。
◎直すべきかどうか、いまだにわからないもの
・printf(3) のエラーチェック
… みんな仕事の場合、printf(3)/sprintf(3)/fprintf(3) の戻り値をチェックしてるの?
stdout or stderr への出力であっても?
> connectに失敗したときにソケットがcloseされない。
うーん。懐かしの malloc/free 論争を思い出してしまいました。その考えを否定はしませんが、わたしはここでは close しません。サンプルコードの可読性を損なうから。実務であっても、即終了するなら close しないと思う。理由は「OS にまかせて実害がないから」。常駐モノならするけど。
> そのreadってhttpで送られてきたデータを受け取っているのでないの?
> データ自体はRFCで規定されている長さまでなら送られてくると思うのだけど。
わたしの知る限りでは、RFC2616 においては HTTP のレスポンスメッセージの最大長は規定されていませんので、理論的には ssize_t の範囲のデータが返ってくると思います (実際は mbuf がもたなくてブロックしてしまうでしょうが)。
ついでに恥をさらしておくと、あのソースは他にもいろいろまずいところがあって、サンプルコードであるという前提であったとしても、以下の問題点があります。参考になれば>葵さん
◎直すべきもの
・write(2) のエラーチェックが漏れている。
・read(2) のエラーチェックが漏れている。
・close(2) のエラーチェックが漏れている。
・おっしゃるとおり、int は ssize_t に直すべき。
ところで負け惜しみのようでかっこ悪いですが、「ssize_t は unsigned」というのは
誤りだと思います (signed じゃないと read(2) が -1 を返せない)。ちなみに FreeBSD
では int でした。
◎直した方がいいなぁと思うもの
・socket(2)・connect(2) などのエラーチェックで、errno を表示した方が親切。
・gethostbyname(3) のエラーチェックは herror(3) あたりを使った方が親切。
・read(s, buf, BUF_LEN) は read(s, buf, sizeof(buf)) に変えたいなぁ。
・strcmp(argv[1], "http://" ) は strcmp(argv[1], "http://" ) != 0 としたい。
・socket(AF_INET, ...) は socket(PF_INET, ...) が正しい (プロトコルファミリの指定なので)
・write(2) で全データを送りきったかどうかのチェックが漏れている。
(ただし、送りきれない場合があるよってのはページをわけて説明したい)
・BUF_LEN は定数の種類を増やすとわかりにくくなると思っていたのですが、
今考えると分けておいた方がいいような気がしてきました。
◎直すべきかどうか、いまだにわからないもの
・printf(3) のエラーチェック
… みんな仕事の場合、printf(3)/sprintf(3)/fprintf(3) の戻り値をチェックしてるの?
stdout or stderr への出力であっても?
スポンサーサイト


