重庆大学计算机网络课程设计4_计算机网络课程设计

2020-02-27 其他范文 下载本文

重庆大学计算机网络课程设计4由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“计算机网络课程设计”。

《计算机网络》课程设计报告

学院:计算机学院

专业:计算机科学与技术6班

指导老师:宋伟

学生姓名:李皓楠、王博韬、魏征、杨俊铸

计算机网络项目书

一,设计目标

Project2:滑动窗口协议模拟

编写一个简单的滑动窗口协议模拟程序,实现两台主机间基于滑动窗口的流控机制。拓扑结构如下图所示:

主机A 传输模拟器器 主机B(1)主机A、主机B及传输模拟器可分别用线程模拟;

(2)传输模拟器用于实现网络传输过程中的丢包、错包和延迟;

(3)定义主机间传输的PDU的结构,包括发送方标识、接收方标识、帧序号、确认号等、窗口大小等,以用于实现Go-Back-N的滑动窗口协议;

(4)在两个主机间传送需要切分成多个帧的大数据块(可直接传输文件进行模拟);(5)一开始的时候,可以让网络仿真网关不丢弃任何帧,也不产生差错帧,检查程序是否能够正常完成传输,为了验证程序是否按照协议工作,让两个程序都显示收发包信息

(6)开启网络仿真网关的丢包功吧一定的丢包率进行丢包,重新运行两个应用程序,检查是否能正常完成文件的传输

(7)

开启网络仿真网关的错包功能,使其按照一定的错包率产生错包,重新运行两个应用程序,检查是否能正常完成文件的传输

(1)

开启网络仿真网关的延时功能,使其按照一定的概率产生延时,重新运行两个应用程序,检查是否能正常完成文件的传。

(2)能直观体现出收发双方窗口的滑动过程或Go-Back过程。

二,任务分配

1.组内分工

代码编写:王博韬、魏征

资料查找、程序测试、报告编写:李皓楠、杨俊铸

三,系统设计

1,基本原理

滑动口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的序号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。接受方为其窗口内的每一个序号保留了一个缓冲区。与每个缓冲区相关联的还有一位,用来指明该缓冲区是满的还是空的。若从滑动窗口的观点来统一看待1比特滑动窗口、后退n及选择重传三种协议,它们的差别仅在于各自窗口尺寸的大小不同而已。1比特滑动窗口协议:发送窗口=1,接收窗口=1;后退N协议:发送窗口>1,接收窗口=1;选择重传协议:发送窗口>1,接收窗口>1。

四,系统实现

考虑设计采用进程模拟,主要算法写在check.h中,编写发送窗口与接收窗口调用实现。发送帧格式为 第一位表示接发者,(0表示数据帧,1表示确认帧)。第二至第四位表示 帧序号(确认号),数据帧由第5位开始到最后为数据与末3位的校验码,确认帧无校验码。

窗口大小为7,采用CRC校验(生成多项式为1010)

1,发送窗口主要函数实现

函数名:send_data2 功能:检测是否需要产生错误,检测是否需要丢包(只丢一次),将string类型转为字符数组,发送缓冲区所有数据,函数名:send_data 功能:发送数据块。

确认帧类型+帧序号+数据部分,加CRC校验码,加入缓冲池

函数名:accept_inf 功能:接受监测

2,接受窗口主要函数实现

函数名:send_ack 功能:确认并请求帧

函数名:data_handling 功能:数据处理

函数名:accept_inf 功能:接受线程信息,进行CRT校验,主要数据处理

3,数据处理部分主要函数实现

函数名:bin_division 功能:二进制除法(被除数与除数位数一致),返回余数(字符串形式)

函数名:bin_division_2 功能:二进制除法(被除数位数不定),返回字符串型余数

函数名:check 功能:校验帧是否发生错误,返回bool值

函数名:add_CRC 功能:为字符串型加上CRC校验码,返回字符串类型

函数名:cut_CRC 功能:为字符串类型剪掉CRC校验码,返回字符串类型

函数名:cut_header 功能:去掉数据头部

函数名:int_to_bin 功能:将帧序号转换为二进制

函数名:bin_to_int 功能:提取出帧序号

函数名:make_mistake 功能:产生错误(第6位取反)

函数名:get_ack 功能:获取ACK序号

五,运行结果

首先开始运行sever程序,界面:

打开cliect

首先检测不丢弃任何帧,也不产生差错帧,输入数据3,3,3空格隔开,运行

Sever界面收到的数据

再监测产生错误,输入数据3,7,7

接受界面

丢包:7.7.3

延时 7 3 7

六,总结

根据实验结果,可以看到延时,丢包和产生错误都成功发生。数据传输和接收同步进行,且产生错误不会阻断发送数据。经过试验过程,我们对滑动窗口协议有了更直观的认识。

七,代码部分 1,check.h #ifndef CHECK_H

//防止重编译

#define CHECK_H #endif

#include #include using std::string;

string bin_division(string dividend,string divisor){

//二进制除法(被除数与除数位数一致),返回余数(字符串形式)int length=dividend.length();string result =“”;if(dividend[0]=='0'){

divisor=“0000000000”;} for(int i=1;i

if(dividend[i]==divisor[i]){

result=result+'0';

}

else{

result=result+'1';

} } return result;}

string bin_division_2(string Dividend,string &Divisor){

返回字符串型余数

int length=Dividend.length();string s_temp=“”;for(int i=0;i

s_temp=s_temp+Dividend[i];} for(int i=3;i

s_temp=s_temp+Dividend[i];

s_temp=bin_division(s_temp,Divisor);} return s_temp;}

bool check(string Dividend,string Divisor){

返回bool值

if(bin_division_2(Dividend,Divisor)==“000”){

return true;} return false;}

string add_CRC(string bin_code,string Divisor){

为字符串型加上CRC校验码,返回字符串类型 string C_bin_code;string s_temp=“000”;

//二进制除法(被除数位数不定),//校验帧是否发生错误,//

s_temp=bin_code+s_temp;s_temp=bin_division_2(s_temp,Divisor);C_bin_code=bin_code+s_temp;return C_bin_code;}

string cut_CRC(string C_bin_code,string Divisor){

//为字符串类型剪掉CRC校验码,返回字符串类型

int length=C_bin_code.length();string bin_code=“”;for(int i=0;i

bin_code=bin_code+C_bin_code[i];} return bin_code;}

string cut_header(string s_temp){

去掉头部

string s_result=“”;int length=s_temp.length();for(int i=4;i

s_result=s_result+s_temp[i];} return s_result;}

string int_to_bin(int i_temp){

帧序号转换为二进制

string s_temp=“”;for(int i=0;i

if(i_temp%2==1){

s_temp='1'+s_temp;

}

else{

s_temp='0'+s_temp;

}

i_temp=i_temp/2;} return s_temp;}

int bin_to_int(string s_temp){

序号

int i_temp=0,i_temp2=4;

//

//将//提取出帧

} for(int i=1;i

i_temp+=i_temp2;} i_temp2=i_temp2/2;} return i_temp;string make_mistake(string s_temp){

//主动产生错误(第6位取反)

if(s_temp[5]=='0'){

s_temp[5]='1';} else{

s_temp[5]='0';} return s_temp;}

int get_ack(char receiveBuf[20]){

//获取ACK序号

int i_temp;i_temp=(int)(receiveBuf[6]-'0');return i_temp;}

2,server.cpp /* 发送帧格式为 第一位表示接发者,(0表示数据帧,1表示确认帧)。第二至第四位表示 帧序号(确认号),数据帧由第5位开始到最后为数据与末3位的校验码,确认帧无校验码。

窗口大小为7,采用CRC校验(生成多项式为1010)。

***11 */ #include

#include

//#include #pragma comment(lib,“ws2_32.lib”)//#include #include

#include #include “check.h” #include using std::ofstream;using std::cout;using std::endl;using std::string;static int buffer[8];

static string data_temp=“”;

//每次收到的数据块,字符串形式存储

const static string Divisor=“1010”;

//CRC校验,校验码为“1010”

static int ack =0;

//需要的帧序号

void send_ack(int ack,SOCKET &serConn){

认并请求帧

char c_temp[8]={'0','1','2','3','4','5','6','7'};string s_temp=“”;s_temp=s_temp+“请求第”+c_temp[ack]+“帧”;char sendBuf[20];strncpy(sendBuf,s_temp.c_str(),20);

send(serConn,sendBuf,strlen(sendBuf)+1,0);

return;}

void data_handling(string s_temp,SOCKET &serConn){

int frame=bin_to_int(s_temp);if(frame==ack){

s_temp=cut_header(s_temp);

data_temp=data_temp+s_temp;

cout

if(s_temp.length()

若帧长度小于17,为数据结束帧。

//打印最终数据

ofstream out_file(“temp_file_accept.txt”);

将数据存入文件

out_file

data_temp=“”;

//初始化数据块,为下一次数据接收做准备

cout

}

ack=(ack+1)%8;

//请求帧序号+1

send_ack(ack,serConn);

//数据处理

//确 //

//

if(ack==7){

//开始下一轮接收

ack=0;

} } return;}

void * accept_inf(void * arg){

监测

SOCKET serConn=*(SOCKET *)arg;

//套接字

int i_temp;

//临时整形数值

char receiveBuf[20];

//用于接收传输帧

string s_temp;

//临时存储文件,用于CRC校验

while(1){

i_temp=recv(serConn,receiveBuf,21,0);

//接收成功返回接收帧的字节长度,或者0,失败则为-1

if(i_temp>0){

s_temp=receiveBuf;

if(check(s_temp,Divisor)){

int order=bin_to_int(s_temp);

cout

s_temp=cut_CRC(s_temp,Divisor);

data_handling(s_temp,serConn);

//进行数据处理

}

else{

cout

}

}

} pthread_exit(0);

线程结束(此次实验不结束)。

}

int main(){ //创建套接字

//接收信息线程,被动

//

WORD myVersionRequest;

WSADATA wsaData;myVersionRequest=MAKEWORD(1,1);

//高(低)8位值,共16位

1.1版本库

int err;err=WSAStartup(myVersionRequest,&wsaData);if(!err){

cout

else{//进一步绑定套接字

cout

SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//创建了可识别套接字

//使用IPV4,与TCP协议

//需要绑定的参数

SOCKADDR_IN addr;

addr.sin_family=AF_INET;

addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

//ip地址,默认本地IP

addr.sin_port=htons(6000);//绑定端口

bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定完成listen(serSocket,5);//其中第二个参数代表能够接收的最多的连接数

//////////////////////////////////////////////////////////////////////////

//开始进行监听

//////////////////////////////////////////////////////////////////////////

SOCKADDR_IN clientsocket;

int len=sizeof(SOCKADDR);

SOCKET serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);

//如果这里不是accept而是connection的话。就会不断的监听

////////////////////////获取到个连接者/////////////////////////////////////

char sendBuf[20]=“两地信道通畅”;

send(serConn,sendBuf,strlen(sendBuf)+1,0);

pthread_t id_accept,id_send;

//接收窗口.线程

pthread_create(&id_accept,NULL,accept_inf,&serConn);pthread_join(id_accept,NULL);closesocket(serConn);//关闭

WSACleanup();//释放资源的操作

return 0;}

3,client.cpp #include #include

//#include #pragma comment(lib,“ws2_32.lib”)#include #include “check.h” #include #include using std::cout;using std::endl;using std::string;using std::ifstream;using std::cin;static int ack_order;const static string Divisor=“1010”;

//CRC校验码

static int error=7;

//错误包

static int delay=2;static int abandon=7;static int accept_ack=0;

void send_data2(int i_First,int i_last,string buffer_temp[],SOCKET &clientSocket){ if(error

//检测是否需要产生错误

buffer_temp[error]=make_mistake(buffer_temp[error]);}

for(int j=i_First;j

//发送缓冲区所有数据

if(j==abandon || j==delay){

//检测是否需要丢包,只丢一次

abandon=7;

}

else{

char sendBuf[20];

//将string类型转为字符数组

strncpy(sendBuf,buffer_temp[j].c_str(),20);

cout

send(clientSocket,sendBuf,strlen(sendBuf)+1,0);

//发送

Sleep(200);

}

} if(delay

//是否需要延迟某包

char sendBuf[20];

//将string类型转为字符数组

strncpy(sendBuf,buffer_temp[delay].c_str(),20);

}

cout

send(clientSocket,sendBuf,strlen(sendBuf)+1,0);

//发送

Sleep(200);delay=7;if(error

//只产生一次错误

buffer_temp[error]=make_mistake(buffer_temp[error]);

error=7;}

return;}

void send_data(SOCKET &clientSocket){

//发送数据块,数据文档为“temp_file_send.txt”

ifstream in_file(“temp_file_send.txt”);int order;

//帧序号

string s_file,file_temp;char file,type='0';

//帧类型

string buffer[7];

//缓冲池

while(!in_file.eof()){

//保证文件所有内容均被读取

int i;

for(i=0;i

order=i;

s_file=“”;

for(int j=0;j

//最多10位作为帧的数据部 in_file.read(&file,1);s_file=s_file+file;}

file_temp =type+int_to_bin(order)+s_file;

//帧类型+帧序号+数据部分

file_temp =add_CRC(file_temp,Divisor);

//加CRC校验码

buffer[i]=file_temp;

//加入缓冲池

}

send_data2(0,i,buffer,clientSocket);

//发送缓冲文件

while(accept_ack

//等待ACK确认,若ACK确认帧序数大于窗口数,开始下一帧

send_data2(accept_ack,i,buffer,clientSocket);

}

} cout

void * accept_inf(void * arg){

//接收监测口

SOCKET clientSocket=*(SOCKET *)arg;

int i_temp;

char receiveBuf[20];

while(1){

i_temp=recv(clientSocket,receiveBuf,21,0);

if(i_temp>0){

accept_ack=get_ack(receiveBuf);

//提取接收帧序号

} } pthread_exit(0);

}

int main(){

//////////////////////////////////////////////连接服务器进程///////////////////////////////////////////////

int err;WORD versionRequired;

WSADATA wsaData;

versionRequired=MAKEWORD(1,1);

err=WSAStartup(versionRequired,&wsaData);//协议库的版本信息 if(!err){ cout

//开始连接

char receiveBuf[20];

recv(clientSocket,receiveBuf,21,0);

cout

//确认初始化

pthread_t id_accept;

//接收线程创建

pthread_create(&id_accept,NULL,accept_inf,&clientSocket);

while(1){

cout

cin>>error>>delay>>abandon;

send_data(clientSocket);

}

send_data(clientSocket);

据块

pthread_join(id_accept,NULL);

closesocket(clientSocket);

WSACleanup();

return 0;}

//发送数

《重庆大学计算机网络课程设计4.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
重庆大学计算机网络课程设计4
点击下载文档
相关专题 计算机网络课程设计 计算机网络 重庆大学 课程设计 计算机网络课程设计 计算机网络 重庆大学 课程设计
[其他范文]相关推荐
    [其他范文]热门文章
      下载全文