
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- その他(開発・運用・管理) Windows serverでマルチキャスト通信の確認をしたいです。MicrosoftよりMPING 1 2023/03/31 01:05
- Wi-Fi・無線LAN PCWi-Fiの設定方法がわからなくて困っています。 4 2022/12/28 18:30
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- Excel(エクセル) エクセル関数の変わった使い方 3 2022/05/13 17:12
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- C言語・C++・C# C言語 3 2022/10/04 15:07
このQ&Aを見た人はこんなQ&Aも見ています
-
ネットワーク切断を検出するには?
C言語・C++・C#
-
ソケットのrecvの戻り値が0
C言語・C++・C#
-
ソケットのクローズについて
C言語・C++・C#
-
-
4
ソケット通信で接続クライアントの上限を設ける
C言語・C++・C#
-
5
system関数のエラー検出
C言語・C++・C#
-
6
ソケット通信内 read関数について
C言語・C++・C#
-
7
read関数をノンブロッキングで実行する(c言語)
C言語・C++・C#
-
8
socket: recvはいつ,どれだけ受け取るのか?
C言語・C++・C#
-
9
エディットボックスで改行
その他(プログラミング・Web制作)
-
10
EDITコントロールで入力できる文字を制限するには?
C言語・C++・C#
-
11
CStringをwchar_tに変換したい
C言語・C++・C#
-
12
エディットボックスの入力制限について
C言語・C++・C#
-
13
非ブロッキングソケットのrecvについて
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
RS-232Cでバイナリデータを受信...
-
Linuxでのシリアル通信について...
-
write関数でEAGAINのエラー発生...
-
WriteFile()でのデータ送信がで...
-
「スイッチングハブのバッファ...
-
ReadFile(GPSとの通信)Win7で...
-
winsockの動作について。
-
WinsockAPIのrecvfromの受信デ...
-
rs232cでの受信データ(mscomm)...
-
C# シリアル通信でデータ受信...
-
C#で通信処理。応答がない場合...
-
再現性の無いバグ
-
Access Violationについて
-
WSH(VBScript)でアプリケーショ...
-
Macターミナルで実行中のプログ...
-
SetWindowPosについて
-
vba listviewにおけるtextのAli...
-
複数スレッドを動作させるのに...
-
SQLの速度をあげるには・・・
-
オフスクリーンサーフェスへの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
「スイッチングハブのバッファ...
-
winsockでソケット通信の開発を...
-
シリアル通信の出力バッファと...
-
WriteFile()でのデータ送信がで...
-
Linuxでのシリアル通信について...
-
WinsockAPIのrecvfromの受信デ...
-
socket: recvはいつ,どれだけ...
-
SerialPortのDataReceivedイベ...
-
ClearCommError呼び出し時のCE_...
-
TCPでの非同期型select関数につ...
-
シリアルポート通信
-
シリアル通信 大きいサイズの...
-
winsockの動作について。
-
ソケット通信内 read関数について
-
COMポートの同時オープン同時読...
-
SocketのSend関数でのCLOSEの検...
-
waveIn、waveOutでの音声録音・...
-
write関数でEAGAINのエラー発生...
-
rs232cでの受信データ(mscomm)...
おすすめ情報