基于滑动窗口协议写的程序(UDP实现)

正好有一个大作业关于用socket实现滑动窗口协议,所以写了一个,模拟接收方与发送方窗口都是2,用两个线程实现。

下面是代码,注释的比较详细了。

socket_udp.h

#include
#include
#include
#include
#include
//#include "winsock2.h"
#pragma     comment(lib,"WS2_32.LIB")

#define SWS 2//定义发送窗口
#define RWS 2//定义接收窗口

typedef u_char SwpSeqno;//定义序列号
typedef HANDLE Semaphore;//定义信号量
typedef HANDLE Event;//定义定时器事件
typedef char Msg;//定义消息的类型

typedef struct {
	SwpSeqno SeqNum;//帧序号
	SwpSeqno AckNum;//已收到确认帧序号
	char	 Flags;//8 bit 的标志
}SwpHdr;
struct sendQ_slot{
	Event timeout;//与发送方相关的超时事件
	Msg *msg;//发送的消息
};
struct recvQ_slot{
	int recevied; //msg是正确的吗?
	Msg *msg;
};
typedef struct {
	//发送方状态
	SwpSeqno LAR;//最近的收到的ACK序号
	SwpSeqno LFS;//最近的发送的帧序号
	Semaphore sendWindowNotFull;//信号量,控制滑动窗口的界
	SwpHdr hdr;
	struct sendQ_slot sendQ[SWS];//发送消息

	//接收方状态
	SwpSeqno NFE;//期待的下一帧的序号
	struct recvQ_slot recvQ[RWS];//接收消息
}SwpState;

//超时线程参数
typedef struct{
	int time;
	Msg frame[11];
}TimeOutType;
socket_udp.cpp

#include"socket_udp.h"

#define HLEN 3//帧头部长度
#define DLEN 8//帧数据长度
#define ALEN 3//ACK帧长度
#define SWP_SEND_TIMEOUT 500//定义超时长度为500ms
#define LINK "127.0.0.1"//定义要发送的对象
#define FLAG_ACK_VALID 'a'//定义ACK帧
#define FLAG_DATA_VALID 'd'//定义数据帧
#define SUCCESS 1;//定义已经成功收到的消息


static void sendSWP(SwpState *state,Msg *frame);//发送函数
static int deliverSWP(SwpState *state,Msg *frame);//接收并返回ACK函数

//发送
static void semWait(Semaphore *sendWindowNotFull);//信号量处理(-1)
static void store_swp_hdr(SwpHdr hdr,char *hbuf);//存储发送的帧头部
static void msgAddHdr(Msg *frame,char *hbuf);//将头部添加到帧上
static void msgSaveCopy(char *msg,Msg *frame);//将消息添加到帧上
static Event evSchedule(Msg *frame,int time);//调用定时器函数
DWORD WINAPI swpTimeout(LPVOID threadtype);//创建定时器线程
static void send_socket(char *addr,Msg *frame,int size);//UDP发送
static void mlisten();//监听数据
static void msend();//发送数据
//接收
static char *msgStripHdr(Msg *frame,int length);//获取帧的头部
static void load_swp_hdr(SwpHdr *hdr,char *hbuf);//帧头部提取字符串
static bool swpInWindow(SwpSeqno AckNum,SwpSeqno LAR,SwpSeqno LFS);//判断收到的帧是否在窗口内
static void evCancel(Event *);//取消超时定时器
static void msgDestroy(Msg *msg);//释放msg空间
static void semSignal(Semaphore *sendWindowNotFull);//信号量处理(+1)
static void prepare_ack(Msg *msg,SwpSeqno n);//组成ACK消息

//全局变量
HANDLE hlisten;
HANDLE hsend;
SwpState *send_state;
Msg *frame;
HANDLE Mutex = CreateMutex(NULL,FALSE,NULL);

void main(){
	//模拟滑动窗口接收和发送过程
	//初始化SwpState,Msg,数据帧组帧
	//启动两个线程,模拟收发
	//监听终止
	frame=(Msg *)malloc(11*sizeof(Msg));
	//初始化消息
	//frame="message";//8个字节的数据
	//初始化状态
	send_state=(SwpState *)malloc(sizeof(SwpState));
	send_state->LAR='0';
	send_state->LFS='0';
	send_state->NFE='0';
	send_state->sendWindowNotFull=CreateSemaphore(NULL,SWS,SWS,NULL);
	if(send_state->sendWindowNotFull==NULL){
		printf("CreateSemaphore error\n",GetLastError());
		exit(0);
	}
	send_state->hdr.SeqNum='0';//3个字节头部
	send_state->hdr.AckNum='0';
	send_state->hdr.Flags='d';
	for(int i=0;isendQ[i].msg=(Msg *)malloc(8*sizeof(Msg));
		send_state->sendQ[i].msg="message";
		send_state->sendQ[i].timeout=NULL;
	}
	for(int i=0;irecvQ[i].msg=(Msg *)malloc(8*sizeof(Msg));
		send_state->recvQ[i].msg="message";
		send_state->recvQ[i].recevied=NULL;
	}
	//初始化UDP函数
	WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,1),&wsaData)){
		printf("Winsock initializing fail\n");
        WSACleanup();
        return;
    }
	//建立监听线程
	hlisten=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) mlisten,NULL,CREATE_SUSPENDED,NULL);
	ResumeThread(hlisten);
	if(hlisten==NULL){
		printf("thread_listen create fail\n");
	}
	hsend=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) msend,NULL,CREATE_SUSPENDED,NULL);
	ResumeThread(hsend);
	if(hsend==NULL){
		printf("thread_send create fail\n");
	}
	Sleep(10000);
    WSACleanup();
}
static void msend(){
	printf("thread_send started\n");
	while(1){
		sendSWP(send_state,frame);
	}
	printf("thread_send quit\n");
}

static void sendSWP(SwpState *state,Msg *frame){
	struct sendQ_slot *slot;//等待发送
	char hbuf[HLEN];//附加在帧头部的字符串

	//等待打开发送窗口
	semWait(&state->sendWindowNotFull);
	WaitForSingleObject(Mutex,INFINITE);
	state->hdr.SeqNum=state->LFS++;
	printf("send %d\n",state->hdr.SeqNum);
	slot=&(state->sendQ[state->hdr.SeqNum % SWS]);
	store_swp_hdr(state->hdr,hbuf);
	msgAddHdr(frame,hbuf);
	msgSaveCopy(slot->msg,frame);
	slot->timeout=evSchedule(frame,SWP_SEND_TIMEOUT);
	send_socket(LINK,frame,HLEN+DLEN);
	ReleaseMutex(Mutex);
}

static int deliverSWP(SwpState *state,Msg *frame){
	SwpHdr hdr;
	char *hbuf;
	hbuf = msgStripHdr(frame,HLEN);
	load_swp_hdr(&hdr,hbuf);
	if(hdr.Flags == FLAG_ACK_VALID){
			//发送方收到一个ACK,处理ACK帧
		if(swpInWindow(hdr.AckNum,state->LAR,state->LFS)){
				do{
					WaitForSingleObject(Mutex,INFINITE);
					printf("send get ack %d\n",hdr.AckNum);
					struct sendQ_slot *slot;
					slot=&state->sendQ[state->LAR++ % SWS];
					evCancel(&slot->timeout);
					//msgDestroy(slot->msg);
					semSignal(&state->sendWindowNotFull);
					ReleaseMutex(Mutex);
				}while(state->LAR==hdr.AckNum);
		}
	}
	if(hdr.Flags == FLAG_DATA_VALID){
			//接收到数据帧,处理数据帧
		WaitForSingleObject(Mutex,INFINITE);
		struct recvQ_slot *slot;
		slot=&state->recvQ[hdr.SeqNum % RWS];
		if(!swpInWindow(hdr.SeqNum,state->NFE,state->NFE+RWS-1)){
			ReleaseMutex(Mutex);
			return SUCCESS;
		}
		msgSaveCopy(slot->msg,frame);
		slot->recevied=TRUE;
		if(hdr.SeqNum==state->NFE){
			Msg *m=(Msg *)malloc(3*sizeof(Msg));
			while(slot->recevied){
				//deliver(HLP,&slot->msg)//传向上层
				printf("receive get data %d\n",hdr.SeqNum);
				printf("%s\n",slot->msg);
				//msgDestroy(slot->msg);
				slot->recevied=FALSE;
				slot=&state->recvQ[state->NFE++ % RWS];
			}
			prepare_ack(m,state->NFE-1);
			send_socket(LINK,m,ALEN);
			msgDestroy(m);
		}
		ReleaseMutex(Mutex);
	}
	return SUCCESS;
}

static void semWait(Semaphore *sendWindowNotFull){
	DWORD	wait_for_semaphore;
	wait_for_semaphore	=  WaitForSingleObject(*sendWindowNotFull,-1);
}

static void store_swp_hdr(SwpHdr hdr,char *hbuf){
	hbuf[0]=hdr.SeqNum;
	hbuf[1]=hdr.AckNum;
	hbuf[2]=hdr.Flags;
}

static void msgAddHdr(Msg *frame,char *hbuf){
	frame[0]=hbuf[0];
	frame[1]=hbuf[1];
	frame[2]=hbuf[2];
}

static void msgSaveCopy(char *msg,Msg *frame){
	int j=0;
	for(int i=3;i<11;i++){
		frame[i]=msg[j];
		j++;
	}
}

static Event evSchedule(Msg *frame,int time){
	TimeOutType *timetype=(TimeOutType *)malloc(sizeof(TimeOutType));//超时线程参数
	timetype->time=time;
	for(int i=0;i<11;i++){
		timetype->frame[i]=frame[i];
	}
	//创建定时器线程
	DWORD targetThreadID;
	HANDLE Timer=CreateThread(NULL,0,swpTimeout,timetype,CREATE_SUSPENDED,NULL);
	ResumeThread(Timer);
	if(Timer==NULL){
		printf("thread_timeout create fail\n");
	}
	return Timer;
}

DWORD WINAPI swpTimeout(LPVOID threadtype){
	printf("thread_timeout started\n");
	TimeOutType *timetype=(TimeOutType *)threadtype;
	int time=timetype->time;
	Msg *frame;
	DWORD result=1;
	frame=timetype->frame;
	SetTimer(NULL,0,time,NULL);

	MSG msg;
    BOOL bRet;

    while (TRUE)
    //该循环捕捉定时器消息   
    {
        bRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        if (bRet ==  - 1){
            // handle the error and possibly exit
        }
        else if (bRet && msg.message == WM_TIMER){//定时器
			//处理超时事件
			printf("send重发%d\n",frame[0]);
			send_socket(LINK,frame,HLEN+DLEN);//超时重发
        }
        else{
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
	printf("thread_timeout_quit");
	return result;
}

static void mlisten(){
    printf("thread_listen started\n");
	SOCKET socket1;
	struct sockaddr_in local;
	struct sockaddr_in from;
	int fromlen =sizeof(from);
	local.sin_family=AF_INET;
	local.sin_port=htons(8808); ///监听端口
	local.sin_addr.s_addr=INADDR_ANY; ///本机

	socket1=socket(AF_INET,SOCK_DGRAM,0);
	bind(socket1,(struct sockaddr*)&local,sizeof(local));
	while (1){
		char buffer[11]={0};
		if (recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR){
				deliverSWP(send_state,buffer);
		}
	}
	closesocket(socket1);
    printf("listen thread quit\n");
}

static void send_socket(char *addr,Msg *frame,int size){
	//UDP发送函数
	SOCKET socket1;

	struct sockaddr_in server;
	int len =sizeof(server);
	server.sin_family=AF_INET;
	server.sin_port=htons(8808); ///server的监听端口
	server.sin_addr.s_addr=inet_addr(LINK); ///server的地址

	socket1=socket(AF_INET,SOCK_DGRAM,0);
     if (sendto(socket1,frame,sizeof(frame),0,(struct sockaddr*)&server,len)!=SOCKET_ERROR){

     }
     closesocket(socket1);
}

static char *msgStripHdr(Msg *frame,int length){
	char *result=(char *)malloc(sizeof(char));
	for(int i=0;iSeqNum=hbuf[0];
	hdr->AckNum=hbuf[1];
	hdr->Flags=hbuf[2];
}

static bool swpInWindow(SwpSeqno seqno,SwpSeqno min,SwpSeqno max){
	SwpSeqno pos,maxpos;
	pos=seqno-min;
	maxpos=max-min+1;
	return pos

具体流程可参考 http://blog.csdn.net/hc260164797/article/details/7558624


你可能感兴趣的:(计算机网络协议)