デバッグ完了

UNIX版から開発しているから、次にWindowsで動かす時のデバッグに時間が掛かった。原因はFD_SETSIZE絡み。UNIXだとFD_SETSIZEのサイズは1024で以下のようにディスクリプタが振られた。

0…標準入力
1…標準出力
2…標準エラー出力
3…ソケットサーバー
4…クライアント1(telnet)
5…クライアント2(telnet)

この時点では数の少ないほうからディスクリプタが振られ1024には遠く及ばないので特に問題ではない。

これがWindowsだとコマンドプロンプトから起動した場合

1956…ソケットサーバー
1928…クライアント1(telnet)
1912…クライアント2(telnet)

直接実行ファイルをダブルクリックして起動した場合でも、

96…ソケットサーバー
124…クライアント1(telnet)
140…クライアント2(telnet)

といった感じで肝心のFD_SETSIZEは64で定義されている為、そのままでは役に立たないどころかオーバーフローを起こしてサーバーが落ちてしまっていた。結局Windowsの場合はFD_SETSIZEを2048に再定義するという方法で逃げた。正直ココまでばらついているとループ回数が増える分不利な気がする。

この時点でチョットの変更でFLASHクライアント用になれるチャットサーバーができました。サーバー自身はデータの中身について全く検査はしてないのとバッファは固定値なので大量にデータを送ると最大値以降の文字は削除されてしまうくらいです。

ソースのダウンロードはこちら(EUC)
socket_server_select

Win32とUNIXで条件分け

只今、メルマガ向けのSocketプログラミングをしているところですが(UNIX版は終了)、同じソースで条件分けする際にヘッダーファイルで定義しないとダメのかなと思っていたら、コンパイラ自身である程度定義が入っているとネット上の情報で発見。実際はコンパイル時に必ず読み込まれるヘッダー辺りにも書いていると思いますが、その内容の今回使用する部分を抜粋。

GCC(UNIX系)の場合
#define __GNUC__

Windowsの場合
#define _WIN32

つまり、ヘッダーファイルの名前が違うとか、ライブラリ関数の差異を埋めるためには、

#ifdef __GNUC__
// ここにUNIX版の処理を記述
#endif
#ifdef
// ここにWindows版の処理を記述
#endif

このようにすればOK

参考:Hey! Java Programming! –移植性–http://www.mars.dti.ne.jp/~torao/program/general/portability.html

厳格にコンパイル

この前から、基本ライブラリはincludeしなくてもコンパイルが通ってしまう件について、コンパイルオプションで厳格にチェックが可能かググってみた。すぐに見つかりました。UNIXでC言語の授業あったのになにやってたんだろオレ。確か98年頃だったかな…。

まずは、-Wallオプション。これで#include忘れを解消。ワーニングがなくなるまで続ける。
あとは -02とか-04ってあるけど今のところは気にしなくてもいいかな。

参考:gccのデバッグ術
http://www-or.amp.i.kyoto-u.ac.jp/algo-eng/db/debug.html