
現在Winsockを用いてTCP/IPメッセージ通信を行うプログラムを作成
しています。
メッセージはヌル文字区切りで送信され、ヌルが発見されると一つの
メッセージの終わりということにしてあります。
このメッセージを時間ウェイトを入れずに連続して送信すると受信側で
正常にデータが受信できず、送信したデータの一部しか受信できません。
ある程度の時間ウェイトを入れてやることで正常に送受信できるように
なります。
受信側の処理において、recvでデータを取得した後にメッセージパーズ
処理を入れているのですがそれほど重い処理でもありません。いろいろ
調べたのですが正常に送受信するときとしないときの違いが連続送信時
に入れる時間ウェイトにあるということしかわかっておりません。
これがTCP/IPの特性なのか私の開発環境(PC・ネットワーク)に起因する
ものなのかがわかりません。どなたかこういった現象についてご経験を
お持ちの方がおられましたらご教授願いたいと思っております。
以上
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
>メッセージはヌル文字区切りで送信され、ヌルが発見されると一つの
>メッセージの終わりということにしてあります。
TCP/IPも含めて、シリアル通信上でこの仕様はあまりよくありません。
通信においては「受信データBYTE数は、それを受信する前にわかって
いる」事が理想となります。つまり可能ならば文字列などの可変長
データは「データ長」+「データ」の順で送信するのが理想となり
ます。この仕様ならデータ部の受信途中で途切れても、残りの数が
自明となります。もちろんデータの先頭を示すシグネチャもあった
方が良いでしょう。
この回答への補足
送信時に送信データサイズ情報も一緒に送るのが理想とおっしゃるのは
確かにそのとおりですね。最初はその方針でした。ただソケットの特性
について知らない部分があったのでこの方法でも原理的には問題ないの
ではと思っていました。
一区切りの送信データを受け取ってからその内容をパーズするという方針
が可能であれば受信側での状態遷移を設計する手間が省けるのでやってみ
たんですがソケットの特性の前に見事にはまりました。

No.2
- 回答日時:
おはようございます。
1回の受信で全データを取得できると思って失敗した事のある者です。
私の場合は、PC間に配置されたルータが送信データ長を少なく絞った為、
受信データが寸断されていました。
HTTP通信であった為、受信側では送信データ長が判断できませんでした。
送信データ長が受信側であらかじめ解っているのでしたら送信データ長まで受信を続ける、
送信データ長が解らない場合はデータ最後にエンドマークを入れ、
それを受信できるまで受信を続ける方法はどうでしょうか?
ご参考までに。
この回答への補足
ご回答ありがとうございます。
1回の受信ですべてのデータが取得できると思い込んではまっているわけ
ではありません。時間ウェイトなしでの連続送信時に送信しただけのデータ
が必ずしも受け取れないという問題でした。
No.1
- 回答日時:
(送信時の)Socktの特性です。
問題はウエイトではなくデータ長にあります。
プログラムの処理能力と物理層の転送能力にはギャップがありますので、当然IP層は送受信用のバッファを持っています。
ウエイトを入れる事で送信バッファが吐き出されバッファに余裕が出来るからIP層がデータの全てを受け取れる状態になっているのだと推測します。
バッファにはもちろん限りがありますので連続送信や長いデータを送る場合に、データの全てが一度に送れる訳ではありません。
実際に送信できたバイト数はsendのリターン値を見れば分かります。
その上で、全てのデータを送り終えるまでポーリングすれば良いです。
この回答への補足
やはりその辺の特性が理由なようですね。大変参考になりました。
なんというかつまり、ある程度のサイズのデータをがしがし送っても
うまくできないものなんですね。
ちなみにsend処理ではsendの返り値を加算して目的の送信データ長
に達するまでループするようにはしてあります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
socket: recvはいつ,どれだけ...
-
winsockでソケット通信の開発を...
-
winsock recvでデータの取得方法
-
RS-232Cでバイナリデータを受信...
-
シリアル通信の出力バッファと...
-
visual c# 2010 シリアル通信ア...
-
UDP処理のエラーについて
-
RS232C通信(PC⇔PLC)
-
recv関数の受信結果について
-
【CAsyncSocket::OnReceive()呼...
-
Macターミナルで実行中のプログ...
-
バックグラウンドのプロセスの...
-
C言語で、メモリを解放しないで...
-
TCP/IP通信時のサーバーからの受信
-
タスクマネージャーのプロセス...
-
家電製品の電力周波数を変える機械
-
並列計算をしたときのシステム...
-
php
-
vba listviewにおけるtextのAli...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
「スイッチングハブのバッファ...
-
WriteFile()でのデータ送信がで...
-
socket: recvはいつ,どれだけ...
-
winsockでソケット通信の開発を...
-
RS-232Cでバイナリデータを受信...
-
SerialPortのDataReceivedイベ...
-
シリアル通信エラー
-
C#で通信処理。応答がない場合...
-
Linuxでのシリアル通信について...
-
シリアル通信の出力バッファと...
-
バイナリデータ受信時のデータ順
-
ReadFileについて
-
トラックバック機能を作りたい
-
ソケット通信内 read関数について
-
recv関数の受信結果について
-
ReadFile(GPSとの通信)Win7で...
-
visual c# 2010 シリアル通信ア...
-
WinsockAPIのrecvfromの受信デ...
-
popen実行時にバッファが空の場合
おすすめ情報