现在的位置: 首页 > 综合 > 正文

通信网络实验——滑动窗口协议模拟实现

2013年12月25日 ⁄ 综合 ⁄ 共 3740字 ⁄ 字号 评论关闭

一.实验目的

实现一个滑动窗口协议的数据传送部分,目的在于使学生更好地理解基本滑动窗口协议的基本工作原理,掌握计算机网络协议的基本实现技术。

二.实验原理

1)窗口机制

滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。

21比特滑动窗口协议

当发送窗口和接收窗口的大小固定为1时,滑动窗口协议退化为停等协议(stop-and-wait)。该协议规定发送方每发送一帧后就要停下来,等待接收方已正确接收的确认(acknowledgement)返回后才能继续发送下一帧。由于接收方需要判断接收到的帧是新发的帧还是重新发送的帧,因此发送方要为每一个帧加一个序号。由于停等协议规定只有一帧完全发送成功后才能发送新的帧,因而只用一比特来编号就够了。

3)后退n协议

由于停等协议要为每一个帧进行确认后才继续发送下一帧,大大降低了信道利用率,因此又提出了后退n协议。后退n协议中,发送方在发完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发来的应答帧,也可以继续发送,且发送方在每发送完一个数据帧时都要设置超时定时器,只要在所设置的超时时间内仍收到确认帧,就要重发相应的数据帧。如:当发送方发送了N个帧后,若发现该N帧的前一个帧在计时器超时后仍未返回其确认信息,则该帧被判为出错或丢失,此时发送方就不得不重新发送出错帧及其后的N帧。

三.实验步骤

1.编写滑动窗口协议的实现程序;

2.在模拟实现,调试并运行自己编写的协议实现程序;

3.了解协议的工作轨迹,如出现异常情况,在实验报告中写出原因分析。

四.实验报告

1.详细描述实验过程。

2.实现具体的窗口滑动协议。

实验在Fedora 16 Linux下完成。实验模拟了滑动窗口协议,服务器向客户端发送数据,客户端判断数据是否错误,错误就重传错误的帧。

主要代码如下,包含一个客户端文件和服务器文件:

/* ****************************************************************
 *      文件名:  client.c
 *      描述:    本文件用于模拟滑窗协议客户端
 *      编译:    Linux:   gcc -lm -o client client.c
 *      可执行文件:      ./client
 *      作者:    段聪 01091138
 ******************************************************************/
#include<stdio.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<sys/types.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#define server_ipaddr "127.0.0.1"
/*************************************************************************
  *      函数名:           main
  *      参数:             NIL
  *      返回值:           NIL
  *      描述:             主函数
***************************************************************************/
main() 
{ 
int std, lfd, len, choice, cport; 
char str[20], str1[20], err[20]; 
struct sockaddr_in saddr, caddr; 
printf("输入端口号:"); 
scanf("%d", &cport); 
std = socket(AF_INET, SOCK_STREAM, 0); 
if(std<0) 
perror("创建socket错误"); 
bzero(&saddr, sizeof(saddr)); 
saddr.sin_family = AF_INET; 
inet_pton(AF_INET, server_ipaddr, &saddr.sin_addr); 
saddr.sin_port = htons(cport); 
connect(std, (struct sockaddr *)&saddr, sizeof(saddr)); 
while(1)
{ 
read(std, str, 20); 
if(strcmp(str, "Exit") == 0) 
{ 
printf("正在退出!\n"); 
break; 
} 
printf("收到: %s   错误?(1 - 是  0 - 否): ", str); 
scanf("%d", &choice); 
if(choice == 0)write(std, "-1", sizeof("-1")); 
else
{
printf("输入发生错误序列的帧号:"); 
scanf("%s", err); 
write(std, err, sizeof(err)); 
read(std, str, 20); 
printf("收到传输帧: %s\n", str); 
} 
} 
close(std); 
}

/* ****************************************************************
 *      文件名:  server.c
 *      描述:    本文件用于模拟滑窗协议服务器端
 *      编译:    Linux:   gcc -o server server.c
 *      可执行文件:      ./server
 *      作者:    段聪 01091138
 ******************************************************************/
#include<sys/types.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
//滑动窗口大小
#define SIZE 4 
/*************************************************************************
  *      函数名:           main
  *      参数:             NIL
  *      返回值:           NIL
  *      描述:             主函数
***************************************************************************/
main() 
{ 
int std, lfd, len, i, j, status, sport; 
char str[20], frame[20], temp[20], ack[20]; 
struct sockaddr_in saddr, caddr; 
printf("输入端口号:"); 
scanf("%d", &sport); 
std = socket(AF_INET, SOCK_STREAM, 0); 
if(std<0) 
perror("创建socket错误"); 
bzero(&saddr, sizeof(saddr)); 
saddr.sin_family = AF_INET; 
saddr.sin_addr.s_addr = htonl(INADDR_ANY); 
saddr.sin_port = htons(sport); 
lfd = bind(std, (struct sockaddr *)&saddr, sizeof(saddr)); 
if(lfd) 
perror("绑定错误"); 
listen(std, 5); 
len = sizeof(&caddr); 
lfd = accept(std, (struct sockaddr *)&caddr, &len); 
printf("输入要发送的文本:"); 
scanf("%s", str);i = 0; 
while(i<strlen(str)) 
{ 
memset(frame, 0, 20); 
strncpy(frame, str+i, SIZE); 
printf("\n传输帧:"); 
len = strlen(frame); 
for(j=0; j<len; j++) 
{ 
printf("%d", i+j); 
sprintf(temp, "%d", i+j); 
strcat(frame, temp); 
} 
write(lfd, frame, sizeof(frame)); 
read(lfd, ack, 20); 
sscanf(ack, "%d", &status); 
if(status == -1) 
printf("\n传输成功!"); 
else 
{ 
printf("接收错误: %d", status); 
printf("\n重传帧:"); 
frame[0] = str[status]; 
frame[1] = '\0';write(lfd, frame, sizeof(frame)); 
} 
i = i + SIZE; 
} 
write(lfd, "Exit", sizeof("Exit")); 
printf("\n正在退出!\n"); 
sleep(2); 
close(lfd); 
close(std); 
} 

使用gcc进行编译:

gcc -o client client.c
gcc -o server server.c

产生两个可执行文件client server

运行程序

抱歉!评论已关闭.