Bob161218 2015-11-29 15:46 采纳率: 0%
浏览 1893

滑动窗口协议模拟代码求补全!!!!!

//发送方sender.cpp文件
#include
#include
#include"sender.h"
#include
#include
#include
#include
#define SLEEPMS 1000
#define MAXPOOL 8
#define RECEIVE_MAX_LENGTH 8
#define MAX_LENGTH 8
#define SEND_MAX_LENGTH 8
CRITICAL_SECTION gCS;

void InitLine(LinkQueue *q) //初始化队列
{
q->front = q->rear = NULL;
}
int QueueEmpty(LinkQueue *q)//判断队列是否为空
{
return q->front == NULL && q->rear == NULL;
}
frame QueueFront(LinkQueue *q)
{
if (QueueEmpty(q))
{
printf("队列为空!\n");
Sleep(SLEEPMS);
exit(0);
}
return q->front->head_data;
}
int QueueLen(LinkQueue *q)//计算队列长度
{
if (QueueEmpty(q))
{
return 0;
}
int num = 0;
Framenode *p = q->front;
while(p != NULL)
{
num++;
p = p->next;
}
return num;
}

void GetFrameFromHost(LinkQueue *q) //数据帧发送完毕(收到确认帧)后,删除发送的数据帧(队头)
{
if(QueueLen(q) >= MAXPOOL)
{
printf("data %d 已准备好\n", q->front->head_data.head.seq);
return;
}
Framenode *p=(Framenode *)malloc(sizeof(Framenode));
memset(p->head_data.head.data, 0, MAX_LENGTH);
srand((unsigned)time(NULL));
p->head_data.size = rand() % MAX_LENGTH; // 帧大小随机生成
memset(p->head_data.head.data, '1', p->head_data.size);
p->head_data.head.ack = -1;
p->head_data.head.kind = data;
p->head_data.head.seq = 0;
p->next =NULL;
if(QueueEmpty(q))
q->front = q->rear=p; // 首帧是待发送的帧
else
{
p->head_data.head.seq = (q->rear->head_data.head.seq + 1)%MAXPOOL;
q->rear->next =p;
q->rear =p;
}
printf("从主机得到:data %d,放入缓存\n", p->head_data.head.seq);
GetFrameFromHost(q); // 由于实验需要,假设主机有足够多的数据帧要发送
}
void DeLine(LinkQueue *q) //将帧数据保存供提交主机,curw是打开的待接收数据的窗口
{
Framenode *p = NULL;
if(QueueEmpty(q))
{
printf("队列为空!\n");
}
else
{
p = q->front;
q->front = p->next;
if (q->rear == p) q->rear = NULL;
printf("发送data %d, %d 成功!从缓存中删除\n", p->head_data.head.seq, p->head_data.size);
free(p);
p = NULL;
}
}

void main()//发送方主函数
{
printf("建立连接 ... \n");
Begin:
WORD wVersionRequested;
WSADATA wsaData; //初始化socket库
wVersionRequested=MAKEWORD(1,1); //两个byte型合并成一个WORD型
int err=WSAStartup(wVersionRequested,&wsaData);
if(err!=0)
{
Sleep(SLEEPMS);
return;
}
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup(); //中止Windows Sockets服务 WSAStartup()成对使用
Sleep(SLEEPMS);
return;
}
socketClient = socket(AF_INET,SOCK_STREAM,0);//监听的套接字
SOCKADDR_IN clientadd;
clientadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
clientadd.sin_family = AF_INET;
clientadd.sin_port = htons(7001);//设置连接端的IP、端口
if(SOCKET_ERROR==connect(socketClient,(SOCKADDR*)&clientadd,sizeof(SOCKADDR)) ) //连接
{
WSACleanup();
Sleep(SLEEPMS);
goto Begin;
}
char getData[RECEIVE_MAX_LENGTH];
memset(getData, 0, RECEIVE_MAX_LENGTH); //清零
if(recv(socketClient,getData,RECEIVE_MAX_LENGTH,0) == SOCKET_ERROR) //接受
{
printf("接受连接提示信息出错!\n");
}
else
{
printf("%s\n",getData);

}
char sendData[SEND_MAX_LENGTH];
memset(sendData, 0, SEND_MAX_LENGTH);
strcpy(sendData, "你好接收方,我是发送方!");
if( SOCKET_ERROR == send(socketClient,sendData,strlen(sendData)+1,0) ) //发送
{
printf("发送连接提示信息出错!\n");
WSACleanup();
closesocket(socketClient);
Sleep(SLEEPMS);
return;
}
printf("按任意键继续!\n");
while (!kbhit()) {}; //等待开始
Sleep(SLEEPMS);
printf("1bit滑动窗口协议:发送方,发送窗口=1\n");
LinkQueue QueueQ;
InitLine(&QueueQ);
frame packetsend; //data
frame packetreceive; // ack,nak
unsigned long tick = GetTickCount();
int ret = 0;
HANDLE hThread;
while(1)
{
GetFrameFromHost(&QueueQ); //从主机取数据帧
memset(&packetsend, 0, sizeof(packetsend));
Sleep(SLEEPMS);
printf("\n");
packetsend = QueueFront(&QueueQ); //取数据帧
ret = send(socketClient, (char *)&packetsend, sizeof(packetsend), 0);//发送data
if(ret == SOCKET_ERROR)
{
printf("发送数据出错!\n");
continue;
}
printf("发送数据帧:data %d, %d\n", packetsend.head.seq, packetsend.size);
const unsigned long timeOut = 5 * 1000; //设置超时计时器 5秒超时
memset(&packetreceive, 0, sizeof(packetreceive));
Sleep(SLEEPMS);
printf("\n");

HANDLE hThrea;
InitializeCriticalSection(&gCS); // 初始化临界区

hThread=CreateThread(NULL, 0, ReceiveFun, (LPVOID)&packetreceive, 0, NULL);

int r = WaitForMultipleObjects(1, &hThread, TRUE, timeOut);

DeleteCriticalSection(&gCS); //与InitializeCriticalSection(&gCS);成对使用

if(ret == SOCKET_ERROR || ret == SOCKET_DISCONN)
{
printf("接受出错!Press any key to continue\n");
while (!kbhit()) {};
continue;
}
if(r == WSA_WAIT_TIMEOUT) //判断超时
{
TerminateThread(hThread, 0); //终止线程
printf("超时重传:data %d, %d\n", packetsend.head.seq,packetsend.size);
}
else if(packetsend.head.seq == packetreceive.head.ack)
{
srand((unsigned)time(NULL));
switch(rand() % 5) //假定产生随机结果,20%的概率超时
{
case 0:
printf("接收方发送回复超时(ack丢失模拟):%d\n", packetsend.head.seq);
printf("超时重传:data %d, %d\n", packetsend.head.seq,packetsend.size);
break;
default:
if(packetreceive.head.kind == ack)
{
printf("接受ack帧:ack %d\n", packetreceive.head.ack);
DeLine(&QueueQ);
}
else if(packetreceive.head.kind == nak)
{
printf("接受nak帧:nak %d\n", packetsend.head.seq);
}
break;
}
}
else printf("帧序号出错: %d\n", packetreceive.head.ack);
if(GetTickCount() - tick > 20 * TIMEOUT) //设置时间20秒
{
printf("持续时间20s. 按q退出,其他键继续\n");
int kbc = getchar();
if(kbc == 'q' || kbc == 'Q')
break;
}
}
printf("按任意键退出!\n");
while (!kbhit()) {};
Sleep(SLEEPMS);
printf("谢谢使用!\n");
WSACleanup();
closesocket(socketClient);
Sleep(SLEEPMS);
}
DWORD WINAPI ReceiveFun(LPVOID pArg)
{
EnterCriticalSection(&gCS);//进入critical section
frame *packetreceive = (frame *)pArg;
ret = recv(socketClient, (char *)packetreceive, sizeof(*packetreceive), 0);
LeaveCriticalSection(&gCS); //线程用毕,离开critical section
return ret;
}
//头文件sender.h部分
#include

typedef enum {data = 1,ack,nak,tout} frame_kind; //帧类型
typedef struct frame_head
{
frame_kind kind; //帧类型
unsigned int seq; //序列号
unsigned int ack; //确认号
unsigned char data[MAX_LENGTH]; //数据
}Head;
typedef struct frame
{
frame_head head; //帧头
unsigned int size; //数据的大小
} Frame;
typedef struct framenode //队列节点类型
{
frame head_data;
struct framenode *next;
} Framenode;
typedef struct

{
Framenode *front; //队头指针
Framenode *rear; //队尾指针
} LinkQueue;

  • 写回答

1条回答 默认 最新

  • devmiao 2015-11-29 18:46
    关注

    现在缺什么代码呢?

    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)