Armadilloフォーラム

イーサネットの接続について

atom

2015年3月26日 15時05分

お世話になっております。
atom 佐藤です。

クライアントとしてサーバーに接続しようとするさいサーバー側が未検出の場合
connectで処理が止まってしまい困っています。

以前はサーバー側が未検出の場合でもすぐに抜けていたと思うのですが、
別件で確認した"プロミスキャスモード"が発生した前後で状況が変わったのではないかと思います。

connect実行時にサーバーが未検出の場合すぐに処理を終わらせる方法があればご教授ください。
よろしくお願いします。

コメント

小西です。

環境が変わった可能性はいっぱいあるのですが、確認するのであれば
・ルーティングテーブルの確認
・ARPキャッシュの更新
等からかと思います。

サーバ-クライアント間がクロス接続(直結)なら
 サーバいない=LinkDown
で即エラーになります。
接続方法が直結からHUBを介した等に環境が変わっているということはないでしょうか?

また、動作から考えるとconnectをブロッキングモードで使用しているのではないでしょうか?
connectをブロッキングモードで使用していると
connectの応答はカーネルコンパイル時のタイムアウト時間まで待つこととなります。
(上記LinkDownの場合は即エラーとなります。)

このため、対策としては
「すぐに処理を終わらす」の時間がタイムアウト時間になりますが、
何をもって「サーバ未検出」とするのか?を「応答がなかったらサーバ不在」を
検出するとのことで書きます。

ノンブロッキングモード+selectで
select時のタイムアウト時間を自前で設定することで実現可能と思います。
タイムアウト時間を短くすると、ネットワークの正しい応答(connectに対するACK)も
取りこぼす可能性があります。

回答ありがとうございます

・クライアント <=> サーバー間の接続について
状況が変わる前後で変更はなくハブを介しての接続です。
クロスケーブルからの直結から変更したということはありません。

・動作モードに関して
サーバーに接続するソケット作成時下記のようにノンブロッキングモードへの変更は行っていないので
ブロッキングモードのままだと思います。
value = 1;
// non blocking socket
if (ioctl(sock_id, FIONBIO, &amp;value) &lt; 0) {
perror("client ioctl");
close (sock_id);
}

ノンブロッキングモード+selectで可能とのことですが
connect()を実行後、10[msec]~50[msec]経過してもサーバーと接続できない場合タイムアウトとしたいのですが可能でしょうか?
この場合、connectのタイムアウトに使用するselectは受信データの検出に使用するselectとは別に用意する必要があるのでしょうか?
サンプルプログラムがあれば参考にしたいのですがないでしょうか?

> ノンブロッキングモード+selectで可能とのことですが
> connect()を実行後、10[msec]~50[msec]経過してもサーバーと接続できない場合タイムアウトとしたいのですが可能でしょうか?

小西さんが書いているとおり、

> ノンブロッキングモード+selectで
> select時のタイムアウト時間を自前で設定することで実現可能

で可能だと思います。

> この場合、connectのタイムアウトに使用するselectは受信データの検出に使用するselectとは別に用意する必要があるのでしょうか?

connect()の場合は、readだけではないので別にした方が良いです。
select関数に渡すファイルディスクリプター集合は、変更される可能性があるので
再度 select関数に渡す前に再設定する必要があります。

http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/select.2.html

システムコール終了時に、 どのファイルディスクリプターの状態が実際に変化したか示すために、 集合の内容が変更される。

> サンプルプログラムがあれば参考にしたいのですがないでしょうか?

検索してみたら、いくつか引っかかりました

- http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-6.html
- http://www.ne.jp/asahi/hishidama/home/tech/lang/socket.html
- http://stackoverflow.com/questions/2597608/c-socket-connection-timeout#…
- http://developerweb.net/viewtopic.php?id=3196

お世話になっております。
atom 佐藤です。

参考のホームページ非常に役に立ちました。

構成としては以下のような構成にすることで期待したとおりの動作となることを確認できました。
(1) ソケットの作成
(2) ソケットをノンブロッキングモードに変更
(3) connect()の実行
(4) サーバー側未検出時の処理を行うためにselect()実行
(5) サーバー未検出の判定処理
select() タイムアウト時サーバー未検出としてソケット破棄

また、不明点がでてきたら利用させていただくかと思います。
その際もよろしくお願いします。