fc2ブログ

無精で短気で傲慢なプログラマ

UNIX や web やプログラムの技術的なことを中心に。

やねうらおさんから http クライアントサンプルコードへのツッコミ

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 への出力であっても?

スポンサーサイト



PageTop

Windows の socket 関数

select() の欠点

だから Windows では実装されないのか。


Windows にも select() はありますよ。ただディスクリプタ一般に使用できる UNIX の
select とは異なり、純粋にソケットにしか使えないので使いづらいです。

また、WSAAsyncSelect やスレッドを使うのが Windows 的かもしれません。

といいつつ わたしは Winsock を使ったことがないので、間違っていたらすみません。
PageTop