
Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、
Client&ServerプログラムをCで作成しているのですが、
そこでのSend関数の使い方についてご助力ください。
Client&Serverプログラムは下記のような動きをします。
[Client]
ServerへConnectした後、複数のDataを数秒間隔でServerへ
送信(send関数使用)します。受信(recvやread関数等)は、
一切行いません。
[Server]
ClientからのConnectを受け付けた後、Clientから受信(recv関数
使用)したDataを標準出力へ表示する。送信(sendやwrite関数
等)は、一切行いません。
さて、ここでもしClientプログラムがCloseを発行したり、マシン
DOWN等の理由でConnectionが切断され、Server側のSocketが
CLOSE_WAIT状態になった場合、Bufferに溜まっていたDataを
すべて受けきった後、recv関数が0を返してくれるので
相手が終了したことがわかります。
ここからが質問のMainです。
では、もしServerプログラムがCloseを発行したり、マシン
DOWN等の理由でConnectionが切断され、Client側のSocketが
CLOSE_WAIT状態になっても、CLOSE_WAIT直後のsend関数が
なぜか正常に処理されてしまいます。無論このDataは、
Server側は受け取りません。この次のsend関数実行時に
EPIPEが返ってくるので、ここでようやくSocketが切断された
ことが判ります。
これを何とかCLOSE_WAIT状態になった直後から、send関数で
切断を検知できるようにできないでしょうか。
よろしくお願いします。
以上

No.4ベストアンサー
- 回答日時:
#3です。
>完全な保証ではないのですが、”送れた/送れない”をきちんと
ログとして残す必要があるのです。
なるほど、そういう事情でしたか。それだと、それなりの信憑性が要求されますね。
>それと最初にご提案いただいたrecvをNonBlockモードで呼び出す
方法ですが、これだとrecvのリターン値は0が返ってこないでしょうか?
Linuxで以下のような、プログラムを組んで確認しました。
//送信前に、ノンブロッキングでrecvする。
ret = recv(sock,rbuf,sizeof(rbuf),MSG_DONTWAIT);
if (ret == -1 && errno == EAGAIN){
//正常なので送信可能
ret = send(sock,msg[i],sendlen,0);
if (ret != sendlen){
//送信エラーの処理
}
}else{
//切断検知時の処理
// CLOSE_WAITになると ret=0が返る
}
サーバー側で切断時、直ちにrecvで戻り値=0となり、エラーの検知ができました。ret==-1 かつ errno==EAGAIN
であれば、回線は正常状態です。
プログラムを組んでまで、確認していたいたのですね。
多謝多謝です。
やはりSendだけでは、厳しそうですね。
tatsu99さんの案も候補にして、今後の方針を探って
いこうとおもいます。
ありがとうございました。

No.3
- 回答日時:
すみません。
全然回答になっていないんですが、>これから作ろうとしている本プログラムでは、実はもっと送信量は
増えるんです。このプログラムは常時接続型を考えていまして、
めったに切断は起こりません。
ということであれば、
CLOSE_WAIT状態になった直後のsend関数で切断を検知できなくても、次のsendで、切断が検知できますので、運用上は特に、問題ないと思うのですが、いかがでしょうか。
CLOSE_WAIT状態になった直後のsend関数で、必ずエラーを検知することに、こだわる必要性がわかりません。できましたら、その理由を教えていただけませんでしょうか。(何故、次のsendでのエラー検知ではいけないのでしょうか)
この回答への補足
幾度も返信いただきありがとうございます。
>CLOSE_WAIT状態になった直後のsend関数で切断を検知できなくても、
>次のsendで、切断が検知できますので、運用上は特に、問題ないと
>思うのですが、いかがでしょうか。
実は、データの保証をしないといけないという事情があります。
完全な保証ではないのですが、”送れた/送れない”をきちんと
ログとして残す必要があるのです。
それと最初にご提案いただいたrecvをNonBlockモードで呼び出す
方法ですが、これだとrecvのリターン値は0が返ってこないでしょうか?
それにしても、Winsockだとただしくエラーが検知できてWSAESHUTDOWNの
エラーコードが取得できるのに、なぜUnixだとだめなんでしょうか。
って愚痴ってもしょうがないですね。
何かよい方法があればお願いします。
よろしくお願いいたします。

No.2
- 回答日時:
>この次のsend関数実行時に
EPIPEが返ってくるので、ここでようやくSocketが切断されたことが判ります。
この次のsend関数実行迄に、相当の時間間隔が発生する為、もっと素早く、障害を検知したいということであれば、以下の方法で対処できるはずです。
まず、ソケットをノンブロッキングモードにします。
次に、一定間隔でrecv関数を呼び出し、サーバーからのデータを受信します。もちろん、サーバはデータを送ってないので、「データなし」の状態が、続きます。しかしながら、Connectionが切断された場合は、recv関数からエラーが返ります。
この回答への補足
返信ありがとうございます。
recv関数をノンブロッキングモードで呼び出すことは、一応考えました。
でも、質問にある
『複数のDataを数秒間隔で・・・・』
というのは、実はテストプログラムなんです。
これから作ろうとしている本プログラムでは、実はもっと送信量は
増えるんです。このプログラムは常時接続型を考えていまして、
めったに切断は起こりません。めったにおきない現象のために、
余計な処理を増やしたくないということもあります。
なんとかないでしょうか、send関数で判定する方法。
それともあきらめるしかないのでしょうか。
わがままで申し訳ありませんが、よろしくお願いします。
No.1
- 回答日時:
>CLOSE_WAIT直後のsend関数が
>なぜか正常に処理されてしまいます。無論このDataは、
>Server側は受け取りません。この次のsend関数実行時に
>EPIPEが返ってくるので、
このあたりの表現が気になるのですが、send のリターン値をちゃんと見ていますか?非負で引数で与えたデータ長より小さい値が返ったら残りデータを再度sendしなければなりません。そのとき-1が返るのでは?
この回答への補足
返信ありがとうございます。
sendのリターン値は、ちゃんと判定しています。
>CLOSE_WAIT直後のsend関数が
>なぜか正常に処理されてしまいます。
このときも、ちゃんとリターン値を判定しています。
このときsendの引数に渡したLengthSizeと同じ
値が返ってきてしまいます。
よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【CAsyncSocket::OnReceive()呼...
-
WriteFile()でのデータ送信がで...
-
socket: recvはいつ,どれだけ...
-
シリアル通信ができません
-
winsockでソケット通信の開発を...
-
winsockの動作について。
-
シリアル通信 大きいサイズの...
-
winsock recvでデータの取得方法
-
Macターミナルで実行中のプログ...
-
powershell を使いカレントディ...
-
バックグラウンドのプロセスの...
-
パソコンの演算速度について
-
エクセルVBA 大容量CSVファイル...
-
VBSの処理中一旦処理を止めて再...
-
【C言語】再帰が時間がかかる...
-
子プロセスの状態を親プロセス...
-
keycodeについて
-
sendkeysにてALT+CTRL+INSERTを...
-
マイコンからプログラムを読み...
-
スーパーのレジで並んでいたら...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
winsockでソケット通信の開発を...
-
socket: recvはいつ,どれだけ...
-
「スイッチングハブのバッファ...
-
VB2005でWin32APIを用いてRS-23...
-
シリアル通信エラー
-
シリアル通信の出力バッファと...
-
バイナリデータ受信時のデータ順
-
WinsockAPIのrecvfromの受信デ...
-
SerialPortのDataReceivedイベ...
-
再現性の無いバグ
-
rs232cでの受信データ(mscomm)...
-
C#で通信処理。応答がない場合...
-
Linuxでのシリアル通信について...
-
WriteFile()でのデータ送信がで...
-
【CAsyncSocket::OnReceive()呼...
-
UDP処理のエラーについて
-
recv関数の受信結果について
-
ReadFile(GPSとの通信)Win7で...
-
VC++ HttpOpenRequest() 正し...
おすすめ情報