TCP/IPのデータ送受信の確実性はどの程度?

このQ&Aのポイント
  • TCP/IPのデータ送受信における確実性について疑問があります。
  • sendとrecvの挙動やデータの欠落について検討しています。
  • データの欠落が発生した場合の再送信方法について教えていただきたいです。
回答を見る
  • ベストアンサー

TCP/IPのデータ送受信の"確実性"はどの程度??

Winsock2を使ってソケットプログラミングをするため通信プロトコルを考えています。そこでソケットの挙動について疑問があります。 sendを複数回使って以下のバイト数のデータを送信したとします。 1.3byte送信[AAA] 2.5byte送信[BBBBB] 3.3byte送信[CCC] このとき正常に通信ができたときは受信側では1~3回のrecvによって [AAABBBBBCCC] というデータが受信できると思います。ここまではいいのですが、疑問があるのは送受信に異常があった場合です。 1.send単位で欠落(再度connectの必要なし)。損失受信データ例[AAACCC]、[BBBBBCCC] 2.TCP上での送信パケット単位で欠落(再度connectの必要なし)。損失データ例[AAABB] 3.send単位で欠落して以後は全て欠落(再度connect必要あり)。損失データ例[AAABBBBB]、[AAA] 4.TCPのパケット単位で欠落して以後は全て欠落(再度connect必要あり)。損失データ例[AAABB] おそらくこれらのいずれかの方法でデータが欠落することになるかと思います。データの再送信をするのであればconnectが必要になるのかという点も分かりません。 ソケットがcloseになったという理由によるデータ欠落であれば4番になるかと思いますが。。。@FreeDのようにドーマントに入るようなネットワークの場合単純にcloseを期待することもできないような気がしますし。。。 どなたか教えていただけないでしょうか?よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.1

基本的にTCP自体が チェックサム等をもち信頼性のあるプロトコルです。 特に1(send単位で欠落)等は途中でデータが損失していますが、 ひとつのパケットに対してシーケンス番号を持っている為 その時点でコネクションロストします。 1~4いずれにしてもデータがおかしい場合 再度connectの必要があります。 あるとするなら 3.send単位で欠落して以後は全て欠落(再度connect必要あり)。損失データ例[AAABBBBB]、[AAA] ただしsend単位ではなくパケット単位です 例えばsendで5Mぐらいのデータを送ろうとしても内部で1024バイトずつに 分割されていたりします。(recvでも1024ずつ受け取ります)

参考URL:
http://akademeia.info/main/lecture2/hyoujyunn_tcp_ip.htm
nitscape
質問者

補足

4番の例になるということですね。自分の中では1番可能性がありそうだと思っていたものです。参考URLもまだ詳しくは見ていませんが役に立ちそうです。ありがとうございます。

その他の回答 (2)

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

すいません。4ですね。 ただ5バイトの文字列(BBBBB)が2つのパケット(BBとBBB)になることは 基本的にはありませんが 勿論プログラム的に必ず5バイトが1パケットで送られることを 前提とするのはよくないです。 1パケットの最大サイズ MTU(Max Transfer Unit)は Windowsならレジストリに設定されていると 思います。 ちなみにWin2kのデフォルトは1024らしいです。 (だからsendが1024ずつに分割されたのかと今納得、、)

参考URL:
http://www.janis.or.jp/adsl/tuneup/tcp_tune.html
  • mssine
  • ベストアンサー率24% (38/156)
回答No.2

アプリケーションから見た場合、sendが正常なら、ちゃんと受信できている。としか判断できません。 完全にブラックボックスの世界です。 なので、sendで送ったバイト数と戻り値が異なっていれば、socketをshutdown & closesocketして、再度、connectする必要があります。

nitscape
質問者

補足

>sendで送ったバイト数と戻り値が異なっていれば、socketをshutdown & closesocketして、再度、connectする必要があります。 MSDNにはsend関数の解説として ---------------- 宣言 int send(SOCKET s,const char FAR *buf,int len,int flags); 戻り値 If no error occurs, send returns the total number of bytes sent, which can be less than the number indicated by len for nonblocking sockets. ---------------- と書かれています。現在使おうと考えているソケットは非ブロッキングです。そのため戻り値では単純にチェックできません。プログラム上でタイムアウトを設定して時間内に指定したバイト数送信できなければcloseと考えるということになりそうですね。

関連するQ&A

  • TCP/IPプログラミングでのselectについて

    selectは使用しているソケットのディスクリプタを登録させれば、send、writeシステムコールからのデータの受信等は検知しますよね。 では、コネクション要求(connect)は、検知するのでしょうか? どなたか回答よろしくお願いします。

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

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

  • TCPとEthernetのデータの分割の役割

    TCPのウィンドウ/フロー制御とethernetのフレームの分割についてご質問です。 書籍を読んでいると TCPはウィンドウ/フロー制御で、一度に送るセグメントサイズを調整しているとあります。 しかしEthernetもフレーム分割を行うとあります。 そうなると、どちらのプロコトルが主体的にデータを分割するのか本を読んでもいまいちわかりません。 例えば、TCPがウィンドウサイズを4500byteにして一度にデータを送信すると データリンク層のEthernetで、4500byteを1500byteずつに三分割するんでしょうか? だとすると、4500byteのデータを送った場合、TCP上では1つのセグメントを送信したことになり Ethernet上だと3つのフレームを送信したことになります。 それとも、TCPが4500byteのデータを送る場合 TCPがデータリンク層で一度に送信できるフレーム長を判断して TCP上で4500byteを一度に送信せずに、1500byteに分割してEthernetに送り Ethernetはその1500byteのデータを三回送信することになるんでしょうか? わかりにくい質問で申し訳ありません。

  • TCP/IPでSENDエラーになってしまう。

    WindowsのTCPでクライアントからサーバに対してsendした際に エラーとなってしまいます。 エラーコードを出力したところ"22"が出力されています。 考えられる事は、大量データの連続送信ですがTCP/IPでは 問題無いと思います。 何か知っているかたおりましたら回答お願い致します。 状況:大量(50K)のデータを連続に送信していると発生 環境:WindowsXP(pro)SP2 VC.net

  • TCP/IPのソケット通信を使用して100ms毎にデータを送信するアプ

    TCP/IPのソケット通信を使用して100ms毎にデータを送信するアプリケーションがあります。 このアプリケーションをPC(Windows XP)上で実行すると、実際には200ms毎にデータを送信しています。 TCP/IPのNagle処理により200ms毎にデータを送信しているようです。 Nagle処理をOFFする為に、レジストリの HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSMQ/Parameters の下に TCPNoDelay REG_DWORD 0x00000001 を追加したのですが、状況が変わりません。200ms単位で送信してしまいます。 レジストリ変更後は、再起動を行っています。 他に設定する方法があるのでしょうか? 宜しくお願いします。

  • TCP/IP のパケットの分断と結合について

    linux で socket を使ってプログラムを作っております。 パケットの頭に、どんな種類のパケットかの情報を入れ、それに続く部分にデータを入れて送っております。受信側では、届いたパケットの頭の情報を見て必要な処理を行う、という流れになっております。 ところが、時々、次のような現象が発生して困っております。 ・送信側で一回のsendで送ったはずのデータが受信側では一回のrecvで届かず、二回のrecvで届く。 ・送信側では二回のsendで送ったつもりなのに、受信側では一回のrecvで2つのパケットが結合したデータが届く。 これはsendとrecvでは普通に起こると想定しなければならない現象なのでしょうか? それとも、linuxマシンの設定に問題があるのでしょうか?

  • TCP/IPで受信エラー

    自作Linuxマシン:クライアント、Windows:サーバの組み合わせで、TCP/IPによる大量受信をすると1000回に1回程度 "could not read received packet length error=7"というエラーがでます。実際に受信内容が化けていることも正常なこともあります。 受信側: Linux-2.6.18-at9 Debian。PowerPc 300MHz 100Base 送信側: Vista Ultimate Core-duo 1.2GHz です。 このエラーはGrepした結果、/drivers/net/temac/adaptor.cというデバイスドライバのFifoReceiveHandlerというモジュールが発しているらしいことが分かりました。 受信側プログラム: void* tcpReceiveThread(void* pParam) という受信専用のスレッドを設け、 while(1){ rcvSize = recv(socket, buf, 1024*9, 0); // Blocking Mode  ・・・・データ処理 } で常時待ちます。 Windows側には別のprocess側チャネルで送信要求をだします。 送信側プログラム:  int ok = send(socket_h, buf, 1024*9, 0); これを1回の送信要求に対し2回続けて実行します。 Windows側は同じPortNoでacceptしてあります。 不具合の推定原因: 1.受信側データ処理が重く、2回目の送信データが処理しきれていない。データ処理は1ms程度 2.受信process側の処理が重く、受信スレッドにリソースが回らない。 3.一回の送受信データ1024*9バイトが大きすぎる。あるいは必要な設定を行っていない。 などが考えられます。実行の時間的制約が厳し過ぎるのかもしれません: 受信側マシン全体で13msの間にコアジョブ3msと2個以上のpacket(1024*9)を受信しなければなりません。 ご示唆願えることがあればお願いいたします。

  • C++ TCP受信 突然切れる

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

  • ソケット通信の送受信遅延

    MFCのCAsyncSockを使ってクライアントとサーバでメッセージの送受信をしています サーバからsend()でメッセージを送信し クライアントはOnReceive()の中でreceive()し メッセージを受信後、応答をsend()で返信します これを10msec間隔で行っているのですが ランダムに送信か受信で300msec前後の遅延が発生します なぜでしょうか? ちなみにソケットオプションで「TCP_NODELAY」を設定しています かなり困っています 気になることでも何でもいいので是非アドバイスをお願いします

  • snifferデータ(TCP)について

    教えてください。 snifferデータで 『TCP:Retransmitted in frame 』と表示されますが、 この意味は何なのでしょうか? シーケンス番号で確認すると、その後同じフレームが 送信されてます。 2回目のフレームは『TCP:Retransmitted in frame 』が 表示されてませんでした。 TCPでの再送されていると思うのですが。。。 『TCP:Retransmitted in frame 』の後に 172 Byte of dataとも表示されておりますが、 実際のデータは206Byteです。

専門家に質問してみよう