
C言語でソケット通信のプログラムを始めて作成しました。
受信時のデータ量が少ない場合は問題ないのですが、データ量が多くなると、
サーバーの受信が、出来たり、出来なかったりと不安定になります。
ログを確認しますと、パケットが勝手に分割されサーバーで受信した場合に、
おかしな動きになることがわかりました。
なぜそのようになるのか、また何がいけないのかわかりません。
どうぞご教授をお願いします。
FD_ZERO(&r_socket);
FD_SET(sock, &r_socket);
width = sock+1;
*leng = 0;
ef = TRUE;
memset(&s,0x00,sizeof(s));
/* タイムアウト設定 */
time.tv_sec = 3;
time.tv_usec = 0;
while(1) {
/* 受信待機 */
ret = select(width, &r_socket, NULL, NULL, &time)
if ( ret < 0 ) {
"受信待機エラー"表示
break;
}
if ( ret = 0 ) {
"タイムアウトエラー"表示
break;
}
/* パケットを受信 */
if ( FD_ISSET(sock, &r_socket)) {
memset(&rb,0x00,sizeof(rb));
read_len = read(sock, rb, sizeof(rb));
"受信した内容をログに出力"
/* 割り込み中断エラーは継続し、その他エラーは終了する */
if ( read_len < 0 ) {
if ( errno == EINTR ) {
continue;
} else {
ef = FALSE;
"受信エラー"表示
break;
}
}
/* クライアントのソケットが閉じた場合は終了する */
if ( read_len == 0 ) {
break;
}
/* データ送信要求を受信した場合は終了する */
if ( rb[read_len-1] == ACK ) {
break;
}
/* 受信バッファーへ取り込み */
if ( rb[read_len-1] == ETX || rb[read_len-1] == ETB ) {
len = read_len - 1;
} else {
len = read_len;
}
for (i = 0;i < len;i++) {
if ( rb[i] != ETB ) {
rsbuf[(*leng)++] = rb[i];
}
}
/* 最終データ時は終了する */
if ( rb[read_len-1] == ETX ) {
break;
}
/* 最終データでない場合はデータ送信要求を送信する */
if ( rb[read_len-1] == ETB ) {
sprintf(trxmsg,"%1c",ACK);
ef = send_socket(sock, strlen(trxmsg), trxmsg);
if ( ef != TRUE ) {
break;
}
}
}
}
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
とりあえず
「サーバーの受信が、出来たり、出来なかったりと不安定になります」
のところ, もっと正確に「どうなるか」を書けませんか? 「こんなデータを送ったはずなのに受け取ってみるとこんな風になってる」というのがあればもっと判断しやすいんだけど....
あと #3 あたりの指摘だけど, たぶん
「rb[read_len-1] == ACK 」とか「rb[read_len-1] == ETX」とかの条件が「本当の最後」以外に成り立ってしまうことはないのか
ということじゃないかなぁ.
この回答への補足
いろいろありがとうございます。
クライアント側で送信データ(1)、(2)、(3)のどれか、または全部があるとすると、
1.送信データ(2)、(3)が
ある場合、送信データ(1)+ETB
ない場合、送信データ(1)+ETX
送信データ(1)を送信
2.送信データ(3)が
ある場合、送信データ(2)+ETB
ない場合、送信データ(2)+ETX
送信データ(2)を送信
3.送信データ3+ETX
送信データ(3)を送信
サーバー側の受信が完了したかを確認せず、
送信処理が正常終了したら、つぎの送信データを送信していました。
それを、
1.サーバーに送信データ(1)送信
2.送信データ(1)の制御文字がETBなら、クライアントに対し、ACKを送信
3.クライアントでACKを受信後、送信データ(2)を送信
4.送信データ(2)の制御文字がETBなら、クライアントに対し、ACKを送信
5.クライアントでACKを受信後、送信データ(3)を送信
に修正したら、正常に送受信するようになりました。
まだ、穴があるかもしれませんが、とりあえず、このままいこうかな?!
と思います。
なにか、不備等がありましたら、指摘のほど、宜しくお願いします。
No.3
- 回答日時:
>まさに案2のように作成したつもりなんですが…
受信データの先頭から順番に制御文字かどうか調べているコードが、質問文に含まれてませんが?
どこでそれをしているつもりですか?
この回答への補足
先頭から順番に制御文字はチェックしていません。
rb[read_len-1] == ETX
受信データの受信長の最終桁で判断しています。
No.2
- 回答日時:
No1です。
>末尾が終了文字でない場合、ループを抜けないようにしているつもりですが、
何の末尾?
送信時の末尾と受信時の末尾は一般に一致しないと書いたのですが、わかりませんか?
例えば、送信側で100バイトのデータを用意して、100バイト目に終了を示すコードを入れて送ったとして、受信側で一回のreadシステムコールで50バイトしか受信できなかった場合、50バイト目を見ても無意味ですよね?
可変長のデータであれば、
案1: 先頭にデータ長を示すものを入れて送り、受信側では最初にデータ長をみて必要なバイト数だけ受け取るまでreadを繰り返す
案2:データに含まれ得ないバイト(またはバイト列)を終わりの印にする。例えばデータが0x20~0xFF だとすると、お書きのようなETXとかETBなど0x00~0x1Fの範囲の制御文字を使う。この場合、受信データの先頭から見ていって、制御文字が出てくるまでreadを繰り返す
この回答への補足
ありがとうございます。
データの末尾が送信時と受信時に違う場合が
あることはわかります。
ですから、終了文字まで繰り返すようにしてある
つもりです。まさに案2のように作成したつもり
なんですが…
何が悪いのでしょうか?
No.1
- 回答日時:
もしかして、例えば100バイト送信すると、受信側で一度に100バイト受け取れると思っていませんか?
一度の受信は何バイトか決まっていませんので、受信データ長を見て、100バイトに満たなければ繰り返し受信してデータを継ぎ足さないといけませんよ。
つまり、何か、受信データの末尾を見ているようですが、それは送信データの末尾とは限らないと言うことです。
この回答への補足
ご回答ありがとうございます。
全ての受信が終了するまで、データを継ぎ足しはしています。
→ rsbuf[(*leng)++] = rb[i];
一文字づつ、別の項目への対比をしています。
データ長が可変のため受信データの末尾で、終了確認をしています。
無限ループのなかで、末尾が終了文字でない場合、
ループを抜けないようにしているつもりですが、繰り返されていないのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Visual Basic(VBA) VBA 請求書自動作成 3 2022/04/24 01:58
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- その他(プログラミング・Web制作) ColabでのPytorchのエラー 1 2022/11/19 20:51
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
- その他(プログラミング・Web制作) 全然分からず困っています。習ったものはPythonで基本的に for~in/if/n=len/inp 2 2023/05/23 21:47
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
TCP/IP のパケットの分断と結合...
-
UDP受信時の通信異常検知について
-
Outlookの「受信日時」「件名」...
-
recv関数の戻り値について
-
RS232cを用いた送信プログラム
-
無線LAN、SIFSについて
-
パケット受信 recvfrom( )につ...
-
C++Builder6.0でのシリアル通信
-
VB2010で、シリアル通信の方法...
-
TCPでパケットロス?
-
シリアル通信時のデータ受信方法
-
PIC-PCシリアル通信プログラム
-
ネットワークでの受信バイト数
-
VC++メッセージの送受信につい...
-
パソコンに詳しい方教えて下さ...
-
複数のテキストファイルの特定...
-
en_US.UTF-8ロケールってどのPO...
-
Zipファイルをエクセルに指定変...
-
cronからtarで圧縮しようとする...
-
Windows上のファイル操作の履歴...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Outlookの「受信日時」「件名」...
-
TCP/IP のパケットの分断と結合...
-
UDP受信時の通信異常検知について
-
VC++メッセージの送受信につい...
-
Outlookの「受信日時」「送信者...
-
TCPでパケットロス?
-
ネットワークでの受信バイト数
-
シリアル通信時のデータ受信方法
-
CRC-CCITTに関しての仕様とサン...
-
VB2010で、シリアル通信の方法...
-
recv関数の戻り値について
-
ソケットプログラミング(配列に...
-
TCPのプログラミングで質問…と...
-
C++Builder6.0でのシリアル通信
-
VB2005でTCP/IPソケット通信で...
-
PC98で232c送信winndowで受信で...
-
赤外線センサーについて
-
C#にてCTI。RS232Cの受信と送信...
-
msgrcv( )で領域破壊?
-
シリアルポートから送られてく...
おすすめ情報