• 締切済み

C++ TCP受信 突然切れる

C++のTCPソケット(recv関数)を使ってサーバからデータを定期的に受信する クライアントを作っているんですが、データの受信中?に突然TCP接続が 切れることがあります。 より正確にはrecvの戻りが0(sizeが0=切断された)になってしまいます。 物理的に配線が切れたとかでもなく、誰も手を触れず放置した状態のときに突然 切れたりとかわけが分かりません。 もしかしてTCPソケットって接続し続けてはいけないとかあるんですかね? 分かる人がいたら宜しくお願いします。

みんなの回答

  • wormhole
  • ベストアンサー率28% (1622/5659)
回答No.2

要求サイズが0になっているという事はありませんか? そのときには切断されていなくても戻り値は0になりますけど。

  • chie65535
  • ベストアンサー率43% (8525/19382)
回答No.1

>物理的に配線が切れたとかでもなく、誰も手を触れず放置した状態のときに突然 >切れたりとかわけが分かりません。 TCP/IPは「受信側と送信側が、直結されている訳ではない」ので、経路の途中で強制切断する可能性があります。 >もしかしてTCPソケットって接続し続けてはいけないとかあるんですかね? 「接続し続けていても構わない」一方で「接続し続けたまま放置した場合、その接続が維持されていると言う保証は無い」です。 例えば、通信を中継している装置で「トラフィック軽減のため、10分間、通信が無かったら、論理的な接続を切る」と言う実装がされている可能性があります。 TCP/IPは、基本的に「バケツリレー」なので「途中で、バケツをリレーしている誰かが、バケツを放り捨てて、通信を切ってしまう可能性」があります。

関連するQ&A

  • TCP通信

    OS:Win2000、VisualBasic.netで開発しています。 現在TCP通信のプログラムを製造しています。 TCPサーバとTCPクライアントのテストアプリケーションを作成し、接続テストを行っているのですが、 サーバとクライアントの接続、データ送受信の確認はできました。 しかし、一度クライアント側から接続を切断(ソケットを消去)し、 再びソケットを生成してコネクト要求を出しても接続が確立できません。 このときサーバ側はなにも操作していません。 終始接続待機状態にしてあります。 ソースがないと分かりにくいかもしれませんが、 何か思い当たることがある方、アドバイスよろしくお願いします。

  • TCPのプログラミングで質問…というか確認しておきたいことが…

    このたびC言語でネットワークプログラミング(TCP)をしているのですが、気になったことがあったので、2点ほど質問させていただきます。 (1)WSock32のsendで一度に送信できる量は65535バイトと以前学んだのですが、受信側がrecvする前にどんどん65535バイト送信していったら受信側のソケットはどんどんいっぱいになってしまいますよね?その場合、限界はあるのでしょうか?また、一度にrecvできる量も65535バイトが限界なのでしょうか?もしそうだとしたら65535バイト以上データがあると取得しても残ってしまうんですか? (2)sendで大きなデータなどを送信した場合、受信側でrecvしたときに途中までのデータを受信してしまったりすることってありますか?たとえば、「"abcde"と送信したのに対し、受信側でrecvしたらとりあえず"abc"まで受信し、次のrecvで残りのデータを受信する」様なことってあるんでしょうか? すべてのデータがちゃんと送信されてからじゃないとrecvで取得することはできなくなっているんでしょうか… とてもとても分かりにくい文章で本当にすみません。 すべてとはいいません、少しでも情報があれば教えていただけませんでしょうか・・・ どうぞよろしくお願いいたしますm(_ _)m

  • ”select”,”FD_ISSET”という関数はMicrosoft Visual C++ 2008 Express Editionで使えますか?

    今、Microsoft Visual C++ 2008 Express Editionでソケット通信のサーバ、クライアントプログラムを作りたくていろいろ調べていて、特に複数クライアントが接続できるサーバを作りたいと思っています。 ただ、どうしてもrecv関数に入ると、1台の端末からのデータ受け取りでステップが停止してしまって、通信を占有してしまい、他のクライアントからのデータを受け付けることができないので、どうすればよいのかと思い、 ググッていたら http://x68000.q-e-d.net/~68user/net/c-echo-2.html このページにselect関数とFD_ISSET関数というのがあって、select関数の引数にデータを設定すれば、FD_ISSET関数の戻り値で作成したソケットに読み取り可能なデータがあるのかを検知できて、検知したらrecv関数でとれるので、これでrecv関数での立ち止まりがないので、複数のクライアントからのデータを行えるというプログラムを見つけました。 ただ、このFD_ISSET関数、select関数はまさにマルチスレッドのやり方だと思うので、Microsoft Visual C++ 2008 Express EditionではMFCがないとのことなのですが、使用することはできるのでしょうか?

  • WinSock32のTCP通信において、recvする前にどれだけの量がソケットにたまっているか調べる方法ってありますか?

    タイトルのとおりなのですが、 WinSock32のTCP通信において、recvする前にどれだけの量がソケットにたまっているかを調べたいのですが、方法が見つかりません。 WinSock32の関数に用意されているのでしょうか? 関数名だけでもいいので教えていただけると助かります。 よろしくお願いいたします

  • TCP通信でrecvで不明な点。

    今、クライアントPCが接続してきて、接続できたら、そのクライアントが渡してくるデータを受け取るプログラムを作っています。下のプログラムを使用しています。 j = recv(NewSocket, RecvBuf, sizeof(RecvBuf), 0); ここで、データをRecvBufというのに入れて、そのデータ量が1212byteだというということがわかりました。それがだいたい5秒に1回程度受信されることがわかりました。 このプログラムだと1212byte受信後に、すぐに j = recv(NewSocket, RecvBuf, sizeof(RecvBuf), 0); このコードを実行しても j = 0が代入されていて、closesocket(NewSocket);が実施されて、接続を切断しているので、その接続を維持したままにできないかと思い、 if(j <= 0) // データを受け取ったか? break; // エラーなら抜ける この部分のプログラムをコメントアウトしてclosesocket(NewSocket);を実施しないようにしたら、5秒以上たっても、1212byteを受信できなくなってしまいました。 この方法だとなぜデータが受信できないのかご教授よろしくお願い致します。 (現在使用しているコードの一部) printf("%d番ポートで接続待機中\n", PORT); // 接続待機中のメッセージ表示 while(1) // サーバループ { i = sizeof(AddrInfo); // SOCKADDR構造体の長さをセットしておく NewSocket = accept(RootSocket, (SOCKADDR *)&AddrInfo, &i); // 接続を待ち受ける if(NewSocket == 0) // エラーがあるか? break; // エラーがあればサーバループを抜ける printf("%sと接続しました\n", inet_ntoa(AddrInfo.sin_addr)); // 接続元のIPアドレスを表示 // TCP/IPデータの受信 while(1) { j = recv(NewSocket, RecvBuf, sizeof(RecvBuf), 0); // クライアントからのデータを読み込む if(j <= 0) // データを受け取ったか? break; // エラーなら抜ける RecvBuf[j] = 0; // 受信データに文字列終端をセットする //if(strstr(RecvBuf, "q")) // qという文字列が含まれているか? // break; // そうならループを抜ける //for(i = 0; i < 30; i++) // 受信した文字列の長さだけ繰り返す // RecvBuf[i] += 1; // 1文字進める if(j != 0) // データを受け取ったか? { for(i = 0; i < 30; i++) // 受信した文字列の長さだけ繰り返す ShowBuf[i] = RecvBuf[i]; // 1文字進める //send(NewSocket, RecvBuf, strlen(RecvBuf), 0); // 加工したデータをクライアントに送信 for(i = 0; i < 30; i++) printf("%#x " , ShowBuf[i]); // サーバから受け取った文字列を表示 printf("cnt %d \n",j); } } //send(NewSocket, RecvBuf, strlen(RecvBuf), 0); // 加工したデータをクライアントに送信 closesocket(NewSocket); // 生成されたソケットを開放 printf("%sと切断しました\n", inet_ntoa(AddrInfo.sin_addr)); // 切断メッセージ表示 }

  • ソケットを使ったTCP通信

    はじめまして. 最近ネットワークの勉強を始めた学生です. ソケットを使ったTCP通信について質問させてください. クライアント側はsocket(), connect()でコネクションを確立した後に何回か連続してsend(), recv()を行いたいのに,サーバ側がファイアウォールや侵入検知システムを使って途中で通信を終了するようにしてしまっている場合,クライアント側は再びコネクションを確立させなければ全てのsend()を行うことはできないのでしょうか? よろしくお願いします.

  • TCP ロスがひどい時の対応

    Win32 C++ でTCP通信をさせています。 パケロスがひどい場合、connectに時間が掛かったり、 接続後send,recv待ちで切断エラーになることが多いようなのですが、 リトライをするにも切断エラーなどを判断するまでに10秒ほどかかったりするのを早く判断して、 sendし直し、またはconnectし直すにはどのように実装すれば可能でしょうか? よろしく御願いします。

  • C言語でのネットワークプログラミング

    現在Linuxを用いてC言語でTCP/IPのサーバ、クライアントプログラムを作成しています。 sendとrecvの正しい使い方がわかっておりません。 一度のrecvですべてのデータを受け取れないことはわかっているのですが、どのように記述するのが良いのでしょうか。1バイトずつrecvするのは大間違いであると何処かのサイトで読みました。 ・現在の仕様 サーバがデータの文字列をsendで送ってくる クライアントはrecvで1バイト読み込みを繰り返し、配列に格納し、\0を見つけるとループを抜ける recvした文字列を画面表示 表示したあとはrecvに戻る

  • TCP通信の切断の検出について

    現在javaでTCP通信でサーバーに接続するタイプの大富豪を製作しております。 そこでTCP接続の切断の検出についてお聞きしたいです。 例えば既にあるオンラインのテーブルゲームなどをプレイしていると、誰かの通信が不安定になるor切断された場合、20~30秒程画面の間、動きが止まり、切断されたプレイヤー以外とのチャット等は可能で20~30秒後に誰かが「落ち」てプレイが続行されます。 この時、バックグラウンドではどのような処理が行われているのでしょうか? (1)TCP接続でデータの送信(受信)を行っているがとあるユーザーは切断されているのでそこが何度も送信(受信)のリトライ→反応なし(ACKを受信できず)→タイムアウトが20~30秒に指定してあり、時間経過後にタイムアウトが呼び出され切断されて続行される。 (2)通信が不安定なユーザーが居て切断/接続を何度も繰り返している。プログラム的に20~30秒不安定な状況が続けば切断するようなプログラムを組んでいる。 (3)その他 また、接続の切断の検出はサーバープログラムのどこで行われるのでしょうか。 (1)各接続クラスのInputStream.readもしくはOutputStream.write (2)Socket接続が切断されればどこかで例外が発生する? (3)その他 詳しい方居られましたら教えて頂けると幸いです。

  • SocketのSend関数でのCLOSEの検知 [Linux]

    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関数で 切断を検知できるようにできないでしょうか。 よろしくお願いします。 以上