- PR -

抜け落ちた番号を再送する方法について(Winsock)

1
投稿者投稿内容
freebird
常連さん
会議室デビュー日: 2006/11/07
投稿数: 22
投稿日時: 2006-11-22 22:08
こんばんわ。
送信側から各パケットに通番を付加し送信。
受信側で取得できなかった通番を割り出し、送信側へ送信。
というプログラムを構築しています。

受信側を以下に示します。

int rbuf[3000]; //global

char recv_Buf[1500]; //local
/*パケット受信するために無限ループ*/
while(1){
 recvfrom(s,recv_Buf,[省略]); //recvfrom関数にて送信側からのパケットを受信
 Seq(recv_Buf);
}

/*未取得シーケンス番号の割り出し*/
Seq(char *recv_Buf){
 int r,x,unseq;
 int m = 0;
 static int c = 0;
 char unseqbuf[30];

memset(unseqbuf,'\0',sizeof(unseqbuf));
sscanf(rbuf,"%d",&r); //通番を整数型で取り出し整数型のrbufへ格納
 rbuf[c] = r

 /*未取得通番の操作*/
 if((rbuf[c]-rbuf[c-1])>=2){
  m=rbuf[c]-rbuf[c-1];
   for(x=1;x<m;x++){
    unseq = rbuf[c-1];
    unseq += x;
    sprintf(unseqbuf,"%d",unseq);
    sendfunc(unseqbuf);
   }
 }
 c++
}

sendfunc(char *unseqbuf){
 sendto //送信側へ送信
}

上記プログラムのように、無限ループによってパケットを受信し、Seq関数内で取得および未取得通番を割り出し、sendfunc内のsendto関数にて未取得パケットを送信しています。

想定しているパケット数は1000個で、送信側から1000パケット送信。
受信側で未取得通番があれば逐次送信側へ送信しています。

[質問事項]
1.未取得シーケンス番号を割り出して、一度配列に格納し、1回の送信(1パケット)で未取得通番を送信するようにしたいのですが、なにか方法はありますでしょうか?

[ メッセージ編集済み 編集者: freebird 編集日時 2006-11-22 22:09 ]

[ メッセージ編集済み 編集者: freebird 編集日時 2006-11-22 22:12 ]

[ メッセージ編集済み 編集者: freebird 編集日時 2006-11-22 22:46 ]
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2006-11-22 22:40
引用:

freebirdさんの書き込み (2006-11-22 22:08) より:
[質問事項]
1.未取得シーケンス番号を割り出して、一度配列に格納し、1回の送信(1パケット)で未取得通番を送信するようにしたいのですが、なにか方法はありますでしょうか?


すばらしい、画期的な方法はありません。単純に受信できたシーケンス番号のリストから、受信できなかったシーケンス番号を割り出すだけです。より高速で、効率の良い方法を知りたいなら、TCPの実装を参考にするのが良いでしょう。
freebird
常連さん
会議室デビュー日: 2006/11/07
投稿数: 22
投稿日時: 2006-11-23 12:36
引用:

甕星さんの書き込み (2006-11-22 22:40) より:
より高速で、効率の良い方法を知りたいなら、TCPの実装を参考にするのが良いでしょう。



分かりました。書き込みありがとうございます。

ひとつプログラムを見ていただけないでしょうか。

[質問箇所]

int ibuf[3100]; //global

/*取得通番の割り出し*/
int Bfunc(char *rbuf){
int num;
sscanf(rbuf,"%d",&num);
return num;
}

/*未取得番号の割り出し*/
int Afunc(char *rbuf){
int no,x;
int m=0;
static int c=0;

sscanf(rbuf,"%d",&r); //通番を整数型で取り出し整数型のrbufへ格納
ibuf[c] = r

/*未取得通番の操作*/
if((ibuf[c]-ibuf[c-1])>=2){
m=ibuf[c]-ibuf[c-1];
for(x=1;x<m;x++){
no = ibuf[c-1];
return no;
no += x;
}
}
c++
}

/*whileの無限ループでパケット受信*/
while(1){
int a = 0;
int b = 0;
char rbuf[1500];

//recvfrom(s,rbuf・・・)関数で受信

a=Afunc(rbuf);
b=ABfunc(rbuf);

fprintf(fp,"%d\\n",a) //未取得通番をファイルへ書き込み
fprintf(fp2,"%d\\n",b) //取得通番をファイルへ書き込み
}

イメージでは、fpに未取得通番が書き込みされ、fp2に取得通番が書き込みされるのですが・・・同じ通番が書き込みされてしまうという現象が生じます。

どこかおかしいのでしょうか?

よろしくお願いします。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-11-23 17:40
引用:

freebirdさんの書き込み (2006-11-23 12:36) より:
イメージでは、fpに未取得通番が書き込みされ、fp2に取得通番が書き込みされるのですが・・・同じ通番が書き込みされてしまうという現象が生じます。



ソースはさらっと眺めただけですが、なぜUDPなのでしょう?
再送を考慮するような場合でUDPを使う必要はないのでは?
ユニキャスト以外の通信が必要なのですか?

UDPではパケットの重複も欠落も普通にありえますよ。
重複の原因がネットワークかプログラムかの切り分けは出来ていますか?
その程度も出来ないようでしたら、UDPでの信頼性の高い通信は無理でしょう。

Programming UNIX Socket FAQをしっかり読んで理解した上で
素直にTCPを使いましょう。TCPでもはまりどころはありますが、
UDPで再送まで含めた実装をするよりは遙かに容易なはずです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-11-23 20:37
引用:

あしゅさんの書き込み (2006-11-23 17:40) より:

Programming UNIX Socket FAQをしっかり読んで理解した上で
素直にTCPを使いましょう。TCPでもはまりどころはありますが、
UDPで再送まで含めた実装をするよりは遙かに容易なはずです。


なんか、「UNIX じゃない、Windows です」なんて返答がある前に、補足。

TCP は、OS に依存しませんから。
あしゅさんが問題にされているのは、プログラムの組み方とか効率的なアルゴリズムとかではなく、もっと下の方、もっと大事な、使用する技術を選ぶための知識です。
freebirdさんが問題とされているところとは違いますが、読んでおいて損はありません。
_________________
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2006-11-23 23:52
ついでにWinsock Programmer's FAQも読んでおくと良い。http://www.kt.rim.or.jp/~ksk/wskfaq-ja/
freebird
常連さん
会議室デビュー日: 2006/11/07
投稿数: 22
投稿日時: 2006-11-24 15:28
あしゅさん、jittaさん、甕星さん
返答ありがとうございます。

引用:

Jittaさんの書き込み (2006-11-23 20:37) より:
なんか、「UNIX じゃない、Windows です」なんて返答がある前に、補足。



たしかにUNIXではなくWindowsを使用しています。ネットワークプログラミングについて書籍を探しているとUNIXやFreeBSDに実装させて紹介している本(8000円程度の本)を見かけます。とてもハードルが高いと実感しています・・・
下位層でプログラミングを行うとなれば、WindowsではなくUNIXを利用しなければならないのでしょうか?

ソケット関数の表記自体異なるようですし・・・
1

スキルアップ/キャリアアップ(JOB@IT)