• 締切済み

TCP/IP通信プログラミングにおけるデータ送信タイミングと受信データ処理のタイミングについて

現在Winsockを用いてTCP/IPメッセージ通信を行うプログラムを作成 しています。 メッセージはヌル文字区切りで送信され、ヌルが発見されると一つの メッセージの終わりということにしてあります。 このメッセージを時間ウェイトを入れずに連続して送信すると受信側で 正常にデータが受信できず、送信したデータの一部しか受信できません。 ある程度の時間ウェイトを入れてやることで正常に送受信できるように なります。 受信側の処理において、recvでデータを取得した後にメッセージパーズ 処理を入れているのですがそれほど重い処理でもありません。いろいろ 調べたのですが正常に送受信するときとしないときの違いが連続送信時 に入れる時間ウェイトにあるということしかわかっておりません。 これがTCP/IPの特性なのか私の開発環境(PC・ネットワーク)に起因する ものなのかがわかりません。どなたかこういった現象についてご経験を お持ちの方がおられましたらご教授願いたいと思っております。 以上

みんなの回答

回答No.3

>メッセージはヌル文字区切りで送信され、ヌルが発見されると一つの >メッセージの終わりということにしてあります。 TCP/IPも含めて、シリアル通信上でこの仕様はあまりよくありません。 通信においては「受信データBYTE数は、それを受信する前にわかって いる」事が理想となります。つまり可能ならば文字列などの可変長 データは「データ長」+「データ」の順で送信するのが理想となり ます。この仕様ならデータ部の受信途中で途切れても、残りの数が 自明となります。もちろんデータの先頭を示すシグネチャもあった 方が良いでしょう。

bh5375
質問者

補足

送信時に送信データサイズ情報も一緒に送るのが理想とおっしゃるのは 確かにそのとおりですね。最初はその方針でした。ただソケットの特性 について知らない部分があったのでこの方法でも原理的には問題ないの ではと思っていました。 一区切りの送信データを受け取ってからその内容をパーズするという方針 が可能であれば受信側での状態遷移を設計する手間が省けるのでやってみ たんですがソケットの特性の前に見事にはまりました。

noname#88772
noname#88772
回答No.2

おはようございます。 1回の受信で全データを取得できると思って失敗した事のある者です。 私の場合は、PC間に配置されたルータが送信データ長を少なく絞った為、 受信データが寸断されていました。 HTTP通信であった為、受信側では送信データ長が判断できませんでした。 送信データ長が受信側であらかじめ解っているのでしたら送信データ長まで受信を続ける、 送信データ長が解らない場合はデータ最後にエンドマークを入れ、 それを受信できるまで受信を続ける方法はどうでしょうか? ご参考までに。

bh5375
質問者

補足

ご回答ありがとうございます。 1回の受信ですべてのデータが取得できると思い込んではまっているわけ ではありません。時間ウェイトなしでの連続送信時に送信しただけのデータ が必ずしも受け取れないという問題でした。

  • buriburi3
  • ベストアンサー率44% (353/792)
回答No.1

(送信時の)Socktの特性です。 問題はウエイトではなくデータ長にあります。 プログラムの処理能力と物理層の転送能力にはギャップがありますので、当然IP層は送受信用のバッファを持っています。 ウエイトを入れる事で送信バッファが吐き出されバッファに余裕が出来るからIP層がデータの全てを受け取れる状態になっているのだと推測します。 バッファにはもちろん限りがありますので連続送信や長いデータを送る場合に、データの全てが一度に送れる訳ではありません。 実際に送信できたバイト数はsendのリターン値を見れば分かります。 その上で、全てのデータを送り終えるまでポーリングすれば良いです。

bh5375
質問者

お礼

bh5375
質問者

補足

やはりその辺の特性が理由なようですね。大変参考になりました。 なんというかつまり、ある程度のサイズのデータをがしがし送っても うまくできないものなんですね。 ちなみにsend処理ではsendの返り値を加算して目的の送信データ長 に達するまでループするようにはしてあります。

関連するQ&A

  • 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)を受信しなければなりません。 ご示唆願えることがあればお願いいたします。

  • 0byteデータの送信と受信

    現在unixでsocketプログラムを書いています。 FTPライクなプログラムを書いているのですが、ファイルを送受信する場合、ファイルの終端をどうするかを考えています。 ファイルサイズを送るのはなしです。 sendで0byteのデータを送り、recvで0byteのデータを受信した場合にファイルの終端に達したとして処理を終らせたいと考えています。 実際、sendでは0byteのデータを送信してもエラーにはなりませんが、recvでは受信できません。 そのような処理はできるのでしょうか? よろしくおねがいします。

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

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

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

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

  • 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を期待することもできないような気がしますし。。。 どなたか教えていただけないでしょうか?よろしくお願いします。

  • 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単位で送信してしまいます。 レジストリ変更後は、再起動を行っています。 他に設定する方法があるのでしょうか? 宜しくお願いします。

  • VC++2010 TCPIP通信の受信処理について

    VC++2010 TCPIP通信の受信処理について質問させていただきました。 現在、VC++2010 MFCのダイアログ でアプリケーションを作成しています。 現在、TCPIP通信で、受信処理のプログラムの所になるんですが、 recv関数を使用してるんですが、この関数は相手側からメッセージが送信される・切断される の イベントが発生しないとrecv関数は終了しません。 ここで質問なんですが、この関数でタイムアウト時間を設けたいのですが どのようにしたら良いかわかりませんでしたので質問させていただきました。 よろしくお願いします。

  • 受信処理の終了条件

    TCP通信でデータを送受信してスループットを測定するプログラムを作成しました。 1.ホストAがデータを送信し,ホストBがそれを受信し、スループットを計算する. 2.ホストBがデータを送信し,ホストAがそれを受信し,スループットを計算する. 3.ホストAがホストBにfinishという文字列を送信する. 4.ホストBがホストAにfinish_recvを送信する. 5.プログラムを終了する. 1と2を行った後,測定終了しましたという意味のfinishをホストAからホストBに送信させます。 ホストAの動作が何らかのアクシデントで2.の途中、つまり受信処理中に止まってしまった場合, ホストBはfinishを受信するためにずっと受信状態で待つことになるとおもうのですが, ホストAは止まっているので,finishが受信されずに永遠に受信待機になると思います. このように何らかのアクシデントで受信処理が終わらなくなった場合、受信しなくても 強制的に受信処理を終わらせることはできますか? 私が考えたのは時間内にデータが送信されてこなかったら強制的に受信を止めさせるというものです. なにかよい方法はありませんか?アドバイスをしていただきたいです.

    • ベストアンサー
    • Java
  • TCP/IP のパケットの分断と結合について

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

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

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

専門家に質問してみよう