Go Back N Vs. Selective Repeat

狂风中的少年 提交于 2019-12-24 18:15:01

问题


Are there any reasons why Go Back N would be preferred over selective repeat for pipelined error recovery ?

Clearly, SR needs a buffer (appropriately sized) at the receiver's end, is that its only weakness ?

Any situation where GBN would be exclusively preffered?


回答1:


My answer might not be too relevant to your question, but it focuses on receive buffer problem of Selective Repeat.

Selective Repeat is much more smart and efficient way of dealing with unreliability of UDP.

But only if it's implemented well. And If we implement it nicely then we don't need to worry about receive buffer.

For example If you choose threading way, then it's quite easy to keep data in buffer. Now you don't need to make one single buffer for whole early arrived data.

So threading way actually goes like this:

  1. Receiver Program going to receive packet.
  2. Check for checksum
  3. If not corrupted, check for duplication using packet Number
  4. Send ACK
  5. If it's first time packet, We going to do next steps, else DO Nothing
  6. Create a Thread for this packet. We are going to process each packet equally irrespective of their sequence.
  7. The function of this thread will use simple semaphore wait and signal mechanism, which we will discuss later.
  8. Save this packet to buffer*, So we don't need a single buffer for all the early arrived packets, but we can make different pointers for each one of them. We will discuss about this later.
  9. After creating thread we going to check if this packet number is just next to our last saved packet. So we can use a packetCounter for that purpose.
  10. If it's just next, we going to signal(semaphore[thisPacketNumber]). This will tell the thread of this packet that it's your turn to go ahead and perform your task, which is simply saving this packet to file.
  11. And if it's not the next to last saved packet, we going to put it in a waiting queue i.e. waitingQueue[thisPacketNumber] = true;

So that's it for the while loop part. We don't need one single buffer to store all these packets or packets that arrived before their previous siblings(packet).

So now we have two challenges, one is to find right data structure for storing each packets separately and another is to keep our thread queue flowing well.

Let's see the solution of our second challenge first.

this is our function that we going to pass to our thread for each original packet.

//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]);
        }


}

Types declaration can vary in Windows & Linux. This one is for Windows.

As you could read the functionality of it in comments provided with code, we can talk about next challenge, i.e. First challenge.

Data-Structure for saving each packet separately.

We simply define a struct and allocate some memory to it's pointer.

So we have:

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

DataBuffer* dataBucket[ESTIMATED_NO_OF_PACKETS];

ESTIMATED_NO_OF_PACKETS can be any number depending on your estimated size of receiving data (No need to be correct), e.g. 500

Or we use something like Recycler Buffer, By freeing the memory of pointer after saving it to file. We can use base and window method, which is like:

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

And after successfully saving 100 packets make base = 100 so we can access the data from buffer like this *dataBucket[base+thisPacketNumber];

And don't forgot to free the memory of each pointer after each save action.

So finally this is how our while original packet processing section going to look like:

//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;
                }

This code is compatible with Windows only, but you can easily change them for Linux or Mac

Some other helpful functions:

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);
}   

Do give some feedback if I forgotten anything to add.



来源:https://stackoverflow.com/questions/29073719/go-back-n-vs-selective-repeat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!