一.实验目的
实现一个滑动窗口协议的数据传送部分,目的在于使学生更好地理解基本滑动窗口协议的基本工作原理,掌握计算机网络协议的基本实现技术。
二.实验原理
(1)窗口机制
滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
(2)1比特滑动窗口协议
当发送窗口和接收窗口的大小固定为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
#include
#include
#include
#include
#include
#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
#include
#include
//滑动窗口大小
#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
使用gcc进行编译:
gcc -o client client.c
gcc -o server server.c
产生两个可执行文件client 和server。
运行程序