返回n相对于 选择重(Go Back N Vs. Selective Repeat)

2019-10-22 06:22发布

是否有早干嘛去了N将优先于对流水线错误恢复选择性重复任何原因?

显然,SR需要在接收机端缓冲区(大小合适),是其唯一的弱点是什么?

任何情况下GBN将专门较受欢迎?

Answer 1:

我的答案可能不是你的问题太重要,但它着重于接受选择性重复的缓冲问题。

选择重是处理UDP的不可靠性更加智能和高效的方式。

但是,只有当它的落实到位。 如果我们很好地实现它,然后我们并不需要担心接收缓冲区。

例如,如果你选择线程方式,那么它很容易将数据保存在缓冲区中。 现在你不需要做一个单一的缓冲区整个初来乍到的数据。

所以线程的方式其实是这样的:

  1. 接收器计划将接收数据包。
  2. 检查校验
  3. 如果没有损坏,使用包号检查重复
  4. 发送ACK
  5. 如果是第一次包 ,我们要做的下一步行动,否则什么都不做
  6. 创建此包线程 。 我们要处理每个数据包同样不论其序列。
  7. 该线程的功能使用简单的信号量的等待和信号机制,我们将在后面讨论。
  8. 保存此包*缓冲区,所以我们并不需要对所有的初来乍到的数据包一个缓冲,但我们可以为他们每个人做出不同的指针。 稍后我们将这个讨论。
  9. 创建线程后,我们会检查这个包号旁边就是我们最后一次保存的数据包。 因此,我们可以用一个packetCounter用于这一目的。
  10. 如果它只是未来,我们将信号(信号灯[thisPacketNumber])。 这将告诉这个包的线程轮到你先走,并完成你的任务,这简直就是保存此包文件
  11. 如果它不是倒数第二个保存的数据包,我们打算把它放在一个等待队列即waitingQueue[thisPacketNumber] = true;

所以这是它while循环的一部分。 我们不需要一个单独的缓存来存储所有这些数据包或数据包,他们的兄弟姐妹先前的(包)之前抵达。

所以,现在我们有两个挑战 ,一个是要找到合适的数据结构,用于分别存储每个数据包,另一个是保持我们的线程队列喷井。

让我们来看看我们的第二个挑战的解决方案。

这是我们的职责,我们要通过我们的线程每个原始数据包。

//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。

正如你可以在提供代码的注释读了它的功能,我们可以谈谈未来的挑战,即第一个挑战

数据结构,分别保存每个数据包。

我们简单地定义一个结构和分配一些内存,它的指针。

因此,我们有:

typedef struct{
    char data[200];
} DataBuffer;

DataBuffer* dataBucket[ESTIMATED_NO_OF_PACKETS];

ESTIMATED_NO_OF_PACKETS可以是任意数量取决于你的估计接收数据的大小(无需是正确的),例如500

或者我们使用类似回收站缓冲区,通过保存到文件后释放指针的内存。 我们可以使用基地和窗口方法,它是这样的:

Set window = 100
AND base = 0
AND ESTIMATED_NO_OF_PACKETS = 100;

并成功地保存100个数据包后使碱= 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);
}   

不要给一些反馈,如果我忘了什么要补充的。



文章来源: Go Back N Vs. Selective Repeat