なぜ私の変数はのWaitForSingleObject後の状態を保持していませんか?
-
26-09-2019 - |
質問
私は、ネットワーククラスの戻るNプロトコルを実装しています。私は私の受信スレッドのソケットが内部のデータを持っている時に知っているのWaitForSingleObjectを使用しています:
int result = WaitForSingleObject(dataReady, INFINITE);
戻るNのために、私は一度に受信機に複数のパケットを送信し、データを操作して、送信側にACKパケットの背中を送信する必要があります。私は、パケットが順不同で到着した場合、私が知っているように、私はACKを送信するたびにインクリメントする変数expectedSEQを持っています。
最初のパケットが到着したときにしかし、私のデバッガはexpectedSEQがインクリメントされているが、次のパケットを操作しているときに、expectedSEQはまだ元の値であることを私に伝えます。
誰もが、これが発生している理由を任意のアイデアを持っていますか?私は、このような
としてif文を置く場合if(recvHeader->seq == expectedSeq+1)
は第2のパケットが正しく登録し、ACKを送信します。明らかに、この2カントーよりも高いパケットの任意の量のために動作しません。
私のイベントは、変数がインクリメントされた後まで、すべてのものを待機させるが、これはどちらか動作しませんでした試みで、セマフォに(元のWaitForSingleObjectを含む)セクション全体をラップしようとしました。
あなたの助けをありがとう!
エリック
リクエストごとに:!より多くのコード
WaitForSingleObject(semaphore, INFINITE);
int result = WaitForSingleObject(dataReady, timeout);
if(result == WAIT_TIMEOUT)
rp->m->printf("Receiver:\tThe packet was lost on the network.\n");
else {
int bytes = recvfrom(sock, recv_buf, MAX_PKT_SIZE, 0, 0, 0);
if(bytes > 0) {
rp->m->printf("Receiver:\tPacket Received\n");
if(recvHeader->syn == 1 && recvHeader->win > 0)
windowSize = recvHeader->win;
//FORMER BUG: (recvHeader->syn == 1 ? expectedSeq = recvHeader->seq : expectedSeq = 0);
if(recvHeader->syn)
expectedSeq = recvHeader->seq;
switch(rp->protocol) {
case RDT3:
...
break;
case GBN:
if(recvHeader->seq == expectedSeq) {
GBNlastACK = expectedACK;
//Setup sendHeader for the protocol
sendHeader->ack = recvHeader->seq;
...
sendto(sock, send_buf, sizeof(send_buf), 0, (struct sockaddr*) &send_addr, sizeof(struct sockaddr_in));
if(sendHeader->syn == 0) { //make sure its not the first SYN connection packet
WaitForSingleObject(mutex, INFINITE);
expectedSeq++;
ReleaseMutex(mutex);
if(recvHeader->fin) {
fin = true;
rp->m->printf("Receiver:\tFin packet has been received. SendingOK\n");
}
}
}
break;
}//end switch
}
解決 2
は、私は私のコード(私のコードは、別のコンピュータ上にあったので、手のタイプ)を入力したように、私は非常に愚かなバグを実現します。私は、パケットの通過0にすべての実行を、それを設定しました。
持っているあなたは午前5時までの符号化されたときに出てくるコードを好きに!
他のヒント
正確にいつ、どのようにあなたがexpectedSeq
増分のですか?あなたは、変数にアクセスするために、クリティカルセクション(またはいくつかの他の同期オブジェクトによって保護されている)または使用expectedSeq
APIを内部にアクセスInterlocked
に必要な場合がありますので、関連するメモリバリアの問題がある可能性があります。
は、例えば、コンパイラはsynchrnoization APIは、コードの重要な領域で起こってからそれを防ぐために必要であるかもしれないので、レジスタにexpectedSeq
の値をキャッシュするかもしれません。 volatile
キーワードを使用すると、ヘルプに思えるが、それはまた、おそらく完全には十分ではないことに注意してください。(それはvolatile
オブジェクトを扱うときに、Microsoftのコンパイラは、完全なメモリバリアを使用しているためMSVC、とのかもしれませんが)。
私はあなたがexpectedSeq
を処理している正確にどのように示すより多くのコードを投稿する必要があると思います。