返回式n-ARQ算法思路
时间: 2023-11-10 08:31:55 浏览: 36
回答:n-ARQ算法是指采用多次传输来确保数据传输正确性的一种算法。其思路是在发送数据时,发送方会等待接收方的回复,以确认数据是否正确接收。如果接收方发现数据有误,会要求发送方重新发送,直到数据传输准确无误为止。返回式n-ARQ算法则是在接收到请求重新发送数据的情况下,发送方会将之前已发送的所有数据全部重新发送,以保证数据传输的正确性。
相关问题
c语言实现返回n-ARQ协议
N-ARQ(即“n”个自动重传请求)是一种数据通信协议,它在传输数据时使用自动重传请求来提高数据传输的可靠性。下面是一个简单的示例代码,演示了如何使用C语言实现N-ARQ协议。
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PACKET_SIZE 1024
#define TIMEOUT 5
// 模拟网络传输
int transmit(char *packet, int size)
{
// 模拟网络延迟
int delay = rand() % 10;
// 模拟传输错误
int error = rand() % 10;
if (error < 5) {
// 传输成功
return delay;
} else {
// 传输失败
return -1;
}
}
// N-ARQ协议的实现
void n_arq(char *data, int size)
{
int seq = 0;
int ack = 0;
int resend = 0;
int timeout = 0;
int delay = 0;
char packet[PACKET_SIZE];
while (ack < size) {
if (seq < size) {
// 发送数据包
printf("Sending packet %d\n", seq);
memcpy(packet, data + seq, PACKET_SIZE);
delay = transmit(packet, PACKET_SIZE);
if (delay < 0) {
// 传输失败,需要重新发送
printf("Packet %d lost, resending...\n", seq);
resend++;
continue;
}
seq += PACKET_SIZE;
timeout = 0;
}
// 接收ACK
delay = transmit("ACK", 3);
if (delay < 0) {
// ACK丢失,需要重新发送
printf("ACK lost, resending...\n");
resend++;
continue;
}
ack += PACKET_SIZE;
// 超时处理
if (timeout > TIMEOUT) {
printf("Timeout, resending packet %d...\n", seq - PACKET_SIZE);
resend++;
timeout = 0;
} else {
timeout += delay;
}
}
printf("Transmission complete, %d packets resent.\n", resend);
}
int main()
{
// 生成随机数据
char data[1024 * 10];
srand(time(NULL));
for (int i = 0; i < sizeof(data); i++) {
data[i] = rand() % 256;
}
// 使用N-ARQ协议传输数据
n_arq(data, sizeof(data));
return 0;
}
```
上面的代码实现了一个简单的N-ARQ协议,它将数据分成了多个固定大小的数据包,并在传输数据包时使用自动重传请求来提高传输的可靠性。在实际应用中,N-ARQ协议通常会使用更复杂的机制来提高传输的效率和可靠性。
c语言实现n-ARQ协议
n-ARQ(n次自动重传请求)是一种数据传输协议,可以在数据传输过程中检测丢失的数据包并进行重传,以确保数据的完整性和可靠性。下面是一个简单的C语言实现n-ARQ协议的示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SEQ 1
#define MAX_PKT 1024
#define TIMEOUT 5
typedef enum {frame_arrival, timeout, crc_err} event_type;
typedef struct {
char data[MAX_PKT];
} packet;
typedef struct {
int seq;
int ack;
int crc;
packet info;
} frame;
static int phl_ready = 0;
int between(int a, int b, int c) {
if(((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a))) {
return 1;
} else {
return 0;
}
}
void send_data(int frame_nr, int frame_expected, packet buffer[]) {
frame s;
s.info = buffer[frame_nr % MAX_SEQ];
s.seq = frame_nr;
s.ack = (frame_expected + MAX_SEQ - 1) % MAX_SEQ;
s.crc = 0;
for(int i = 0; i < sizeof(frame); i++) {
s.crc += *((char*)&s + i);
}
printf("Sending frame %d\n", frame_nr);
phl_ready = 0;
send_frame(s);
start_timer(frame_nr % MAX_SEQ);
}
void protocol5(void) {
int ack_expected = 0;
int next_frame_to_send = 0;
int frame_expected = 0;
int too_far = MAX_SEQ;
packet buffer[MAX_SEQ];
frame r;
int nbuffered = 0;
int i;
for(i = 0; i < MAX_SEQ; i++) {
buffer[i].data[0] = '0' + i;
}
while(1) {
wait_for_event(&event);
switch(event.type) {
case(frame_arrival):
recv_frame(&r);
if(r.seq == frame_expected) {
printf("Receiving frame %d\n", frame_expected);
if(r.crc != 0) {
printf("CRC error\n");
send_data((ack_expected + MAX_SEQ - 1) % MAX_SEQ, frame_expected, buffer);
} else {
nbuffered--;
frame_expected = (frame_expected + 1) % MAX_SEQ;
ack_expected = (ack_expected + 1) % MAX_SEQ;
stop_timer(frame_expected % MAX_SEQ);
}
} else {
printf("Receiving frame %d\n", r.seq);
}
while(between(ack_expected, r.ack, next_frame_to_send)) {
nbuffered--;
stop_timer(ack_expected % MAX_SEQ);
ack_expected = (ack_expected + 1) % MAX_SEQ;
}
break;
case(timeout):
printf("Timeout %d\n", frame_expected);
send_data((ack_expected + MAX_SEQ - 1) % MAX_SEQ, frame_expected, buffer);
break;
case(crc_err):
printf("CRC error\n");
send_data((ack_expected + MAX_SEQ - 1) % MAX_SEQ, frame_expected, buffer);
break;
default:
break;
}
if(nbuffered < MAX_SEQ && phl_ready) {
printf("Buffering packet %d\n", next_frame_to_send);
send_data(next_frame_to_send, frame_expected, buffer);
next_frame_to_send = (next_frame_to_send + 1) % MAX_SEQ;
nbuffered++;
}
if(between(ack_expected, r.ack, next_frame_to_send)) {
printf("Acknowledge %d\n", r.ack);
}
}
}
int main(int argc, char const *argv[]) {
protocol5();
return 0;
}
```
在这个示例中,我们使用了一个简单的环形缓冲区来存储数据包。我们使用一个循环变量`next_frame_to_send`来追踪下一个要发送的数据包,使用`frame_expected`来追踪下一个期望接收的数据包,使用`ack_expected`来追踪下一个期望接收的确认帧。
在主程序中,我们调用了`protocol5`函数来实现n-ARQ协议。在该函数中,我们使用一个无限循环来等待事件的发生。当一个帧到达时,我们首先检查它的序号是否与期望的一致,如果一致,则说明这是我们期望的帧。我们首先检查CRC校验是否通过,如果通过,则将帧的数据包存入缓冲区,然后更新期望的帧号和确认帧号,并停止计时器。如果CRC校验失败,则重新发送上一个确认帧。
如果我们收到的不是期望的帧,则说明它是一个老的或未来的帧,我们只需简单地丢弃即可。
当一个计时器超时时,我们重新发送上一个确认帧。如果我们收到了一个CRC校验错误,则也重新发送上一个确认帧。
如果我们的缓冲区中有空闲空间,并且物理层准备好了发送下一个帧,则我们将下一个帧发送出去,并更新`next_frame_to_send`和`nbuffered`变量。
最后,如果我们收到了一个确认帧,则我们更新`ack_expected`变量并打印一条确认消息。