【发布时间】:2015-05-18 09:12:55
【问题描述】:
对于流水线式错误恢复,Go Back N 是否比选择性重复更受青睐?
显然,SR 在接收端需要一个缓冲区(大小合适),这是它唯一的弱点吗?
在任何情况下都优先选择 GBN?
【问题讨论】:
标签: networking tcp protocols tcp-ip
对于流水线式错误恢复,Go Back N 是否比选择性重复更受青睐?
显然,SR 在接收端需要一个缓冲区(大小合适),这是它唯一的弱点吗?
在任何情况下都优先选择 GBN?
【问题讨论】:
标签: networking tcp protocols tcp-ip
选择性重复是处理 UDP 不可靠性的更智能和有效的方法。
但前提是它实施得很好。 如果我们很好地实现它,那么我们就不需要担心接收缓冲区。
例如如果你选择threading方式,那么将数据保存在缓冲区中是很容易的。 现在您不需要为整个早期到达的数据创建一个缓冲区。
所以线程的方式实际上是这样的:
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 和 Linux 中可能有所不同。 这个适用于 Windows。
您可以在随代码提供的 cmets 中阅读它的功能,我们可以讨论下一个挑战,即第一个挑战。
分别保存每个数据包的数据结构。
我们只需定义一个结构并为其指针分配一些内存。
所以我们有:
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);
}
如果我忘记添加任何内容,请提供一些反馈。
【讨论】: