是否有任何理由为什么Go Back N优先于选择性重复进行流水线错误恢复?
显然,SR在接收端需要缓冲区(大小合适),这是它唯一的弱点吗?
GBN会独占优先的任何情况吗?
答案 0 :(得分:0)
选择性重复是处理UDP不可靠性的更加智能和有效的方法。
但前提是它的实施得很好。 如果我们很好地实现它,那么我们不需要担心接收缓冲区。
例如,如果您选择线程方式,那么将数据保存在缓冲区中非常容易。 现在,您不需要为整个早到数据制作一个缓冲区。
因此,线程方式实际上是这样的:
packetCounter
来实现此目的。waitingQueue[thisPacketNumber] = true;
这就是while循环部分。 我们不需要一个缓冲区来存储在它们之前的兄弟(数据包)之前到达的所有这些数据包或数据包。
现在我们有两个挑战,一个是找到正确的 数据结构 来分别存储每个数据包,另一个是保持我们的< strong> 线程队列 流畅。
让我们先看看第二次挑战的解决方案。
这是我们的函数,我们将为每个原始数据包传递给我们的线程。
//this is our packetQueue
//Each packet will be alloted one instance of this functionality using threads
//So here, we have packetNumber of each respective packet
//Each packet will call wait(on Its Respective Semaphore) , shown below.
//Since we are going to initiate there respective semaphores from 0;
//They will enter in a waiting state and will only awake after getting signal from somewhere else or another packet.
//So As we saw in the while loop section, we are signaling the current packet if it's next to last saved packet.
//Once this packet got signaled, it will perform it's task, i.e. saving this packet into file.
//*****Increment the packetCounter++
//And then check if next packet in the sequence is waiting in the queue.....
//here we are using waitingThread[] boolean array for that purpose, you can use waitingQueue[] as it's name.
//if yes then signal next packet.
//And **TADA** it's done
unsigned long CALLBACK packetQueue(void *pn){
int packetNumber = (int) pn;
wait(packet[packetNumber]);
char *dt = dataBucket[packetNumber]->data;
save_line_into_file(dt);
waitingThread[packetNumber] = false;
packetCounter++;
if(waitingThread[packetNumber+1]){
signal(packet[packetNumber+1]);
}
}
类型声明在Windows和&amp; Linux操作系统。 这个适用于Windows。
正如您可以在代码提供的评论中阅读它的功能,我们可以谈论下一个挑战,即第一次挑战。
用于单独保存每个数据包的数据结构。
我们只是定义一个结构并为它指定一些内存。
所以我们有:
typedef struct{
char data[200];
} DataBuffer;
DataBuffer* dataBucket[ESTIMATED_NO_OF_PACKETS];
ESTIMATED_NO_OF_PACKETS
可以是任意数字,具体取决于您估算的接收数据大小(无需更正),例如500
或者我们使用像Recycler Buffer这样的东西, 通过将指针的内存保存到文件后释放它。 我们可以使用base和window方法,如:
Set window = 100
AND base = 0
AND ESTIMATED_NO_OF_PACKETS = 100;
成功保存100个数据包后,使base = 100
所以我们可以像缓冲区*dataBucket[base+thisPacketNumber];
在每次保存操作后,不要忘记释放每个指针的内存。
所以最后这就是我们原始数据包处理部分的样子:
//After sending ACK of this packet
//We can check if this is duplicate packet or not
//if(original){...
//Create Semaphore for this packetThread
packet[packetNumber] = create(0);
//Create Thread for this packet
//We gonna treat each request equally
//that's why we are putting each thread in queue.
//And a dataBucket Structure to pass parameters to thread
dataBucket[packetNumber] = (DataBuffer*)malloc(sizeof(DataBuffer));
strcpy(dataBucket[packetNumber]->data, data);
CreateThread(NULL,0,packetQueue,(void *)packetNumber,0,&tid);
//Now check if this the next packet in queue of not.
//If yes then signal this packet
//else put it in queue
if((packetCounter+1) == packetNumber){
signal(packet[packetNumber]);
}else{
waitingThread[packetNumber] = true;
}
此代码仅与Windows兼容,但您可以轻松地为Linux或Mac更改它们
其他一些有用的功能:
void wait(semaphore h) { // wait for a semaphore
WaitForSingleObject( h, MAXLONG);
}
void signal(semaphore h) { // signal a semaphore
ReleaseSemaphore(h,1,NULL);
}
semaphore create(int v) { // create a semaphore with value v
return CreateSemaphore(NULL,(long)v, MAXLONG, NULL);
}
如果我忘记添加任何内容,请提供一些反馈。