《计算机网络》实验指导书(软件学院2015) - 图文 下载本文

《计算机网络》实验指导书

Sleep(500); } //等待Ack,若没有收到,则返回值为-1,计数器+1 recvSize = recvfrom(sockServer,buffer,BUFFER_LENGTH,0,((SOCKADDR*)&addrClient),&length); if(recvSize < 0){ waitCount++; //20次等待ack则超时重传 if (waitCount > 20) { timeoutHandler(); waitCount = 0; } }else{ //收到ack ackHandler(buffer[0]); waitCount = 0; } Sleep(500); break; } } } sendto(sockServer, buffer, strlen(buffer)+1, 0, (SOCKADDR*)&addrClient, sizeof(SOCKADDR)); Sleep(500); } //关闭套接字,卸载库 closesocket(sockServer); WSACleanup(); return 0; } (2) 客户端设计参考 1) ACK数据帧定义

由于是从服务器端到客户端的单向数据传输,因此ACK数据帧不包含任何数据,只需要将ACK发送给服务器端即可。

ACK字段为一个字节,表示序列号数值; 末尾放入0,表示数据结束。

2)命令设置

21

《计算机网络》实验指导书

客户端的命令和服务器端的解析命令向对应,获取当前用户输入并发送给服务器并等待服务器返回数据,如输入“-time”得到服务器的当前时间。

此处重点介绍“-testgbn [X] [Y]”命令,[X],[Y]均为[0,1]的小数,其中: [X]表示客户端的丢包率,模拟网络中报文丢失;

[Y]表示客户端的ACK的丢失率。(使用随机函数完成)。 如果用户不输入,则默认丢失率均为0.2。 3)源代码

// GBN_client.cpp : 定义控制台应用程序的入口点。 // #include \#include #include #include #pragma comment(lib,\ #define SERVER_PORT 12340 //接收数据的端口号 #define SERVER_IP \服务器的IP地址 const int BUFFER_LENGTH = 1026; const int SEQ_SIZE = 20;//接收端序列号个数,为1~20 /****************************************************************/ /* -time 从服务器端获取当前时间 -quit 退出客户端 -testgbn [X] 测试GBN协议实现可靠数据传输 [X] [0,1] 模拟数据包丢失的概率 [Y] [0,1] 模拟ACK丢失的概率 */ /****************************************************************/ void printTips(){ printf(\ printf(\ -time to get current time |\\n\ printf(\ -quit to exit client |\\n\ printf(\ -testgbn [X] [Y] to test the gbn |\\n\ printf(\} //************************************ // Method: lossInLossRatio // FullName: lossInLossRatio // Access: public // Returns: BOOL 22

《计算机网络》实验指导书

// Qualifier: 根据丢失率随机生成一个数字,判断是否丢失,丢失则返回TRUE,否则返回FALSE // Parameter: float lossRatio [0,1] //************************************ BOOL lossInLossRatio(float lossRatio){ int lossBound = (int) (lossRatio * 100); int r = rand() % 101; if(r <= lossBound){ return TRUE; } return FALSE; } int main(int argc, char* argv[]) { //加载套接字库(必须) WORD wVersionRequested; WSADATA wsaData; //套接字加载时错误提示 int err; //版本2.2 wVersionRequested = MAKEWORD(2, 2); //加载dll文件Scoket库 err = WSAStartup(wVersionRequested, &wsaData); if(err != 0){ //找不到winsock.dll printf(\ return 1; } if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) !=2) { printf(\ WSACleanup(); }else{ printf(\ } SOCKET socketClient = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrServer; addrServer.sin_addr.S_un.S_addr = inet_addr(SERVER_IP); addrServer.sin_family = AF_INET; addrServer.sin_port = htons(SERVER_PORT); //接收缓冲区 char buffer[BUFFER_LENGTH]; ZeroMemory(buffer,sizeof(buffer));

23

《计算机网络》实验指导书

int len = sizeof(SOCKADDR); //为了测试与服务器的连接,可以使用 -time 命令从服务器端获得当前时间 //使用 -testgbn [X] [Y] 测试GBN 其中[X]表示数据包丢失概率 // [Y]表示ACK丢包概率 printTips(); int ret; int interval = 1;//收到数据包之后返回ack的间隔,默认为1表示每个都返回ack,0或者负数均表示所有的都不返回ack char cmd[128]; float packetLossRatio = 0.2; //默认包丢失率0.2 float ackLossRatio = 0.2; //默认ACK丢失率0.2 //用时间作为随机种子,放在循环的最外面 srand((unsigned)time(NULL)); while(true){ gets_s(buffer); ret = sscanf(buffer,\ //开始GBN测试,使用GBN协议实现UDP可靠文件传输 if(!strcmp(cmd,\ printf(\process\ printf(\loss ratio of packet is %.2f,the loss ratio of ack is %.2f\\n\ int waitCount = 0; int stage = 0; BOOL b; unsigned char u_code;//状态码 unsigned short seq;//包的序列号 unsigned short recvSeq;//接收窗口大小为1,已确认的序列号 unsigned short waitSeq;//等待的序列号 sendto(socketClient, \strlen(\0, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); while (true) { //等待server回复设置UDP为阻塞模式 recvfrom(socketClient,buffer,BUFFER_LENGTH,0,(SOCKADDR*)&addrServer, &len); switch(stage){ case 0://等待握手阶段 u_code = (unsigned char)buffer[0]; if ((unsigned char)buffer[0] == 205) {

24