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

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

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

socket_udp.h

  1. #include<stdio.h>   
  2. #include<Windows.h>   
  3. #include<stdlib.h>   
  4. #include<time.h>   
  5. #include<math.h>   
  6. //#include "winsock2.h"   
  7. #pragma     comment(lib,"WS2_32.LIB")   
  8.   
  9. #define SWS 2//定义发送窗口   
  10. #define RWS 2//定义接收窗口   
  11.   
  12. typedef u_char SwpSeqno;//定义序列号   
  13. typedef HANDLE Semaphore;//定义信号量   
  14. typedef HANDLE Event;//定义定时器事件   
  15. typedef char Msg;//定义消息的类型   
  16.   
  17. typedef struct {  
  18.     SwpSeqno SeqNum;//帧序号   
  19.     SwpSeqno AckNum;//已收到确认帧序号   
  20.     char     Flags;//8 bit 的标志   
  21. }SwpHdr;  
  22. struct sendQ_slot{  
  23.     Event timeout;//与发送方相关的超时事件   
  24.     Msg *msg;//发送的消息   
  25. };  
  26. struct recvQ_slot{  
  27.     int recevied; //msg是正确的吗?   
  28.     Msg *msg;  
  29. };  
  30. typedef struct {  
  31.     //发送方状态   
  32.     SwpSeqno LAR;//最近的收到的ACK序号   
  33.     SwpSeqno LFS;//最近的发送的帧序号   
  34.     Semaphore sendWindowNotFull;//信号量,控制滑动窗口的界   
  35.     SwpHdr hdr;  
  36.     struct sendQ_slot sendQ[SWS];//发送消息   
  37.   
  38.     //接收方状态   
  39.     SwpSeqno NFE;//期待的下一帧的序号   
  40.     struct recvQ_slot recvQ[RWS];//接收消息   
  41. }SwpState;  
  42.   
  43. //超时线程参数   
  44. typedef struct{  
  45.     int time;  
  46.     Msg frame[11];  
  47. }TimeOutType;  
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
//#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

  1. #include"socket_udp.h"   
  2.   
  3. #define HLEN 3//帧头部长度   
  4. #define DLEN 8//帧数据长度   
  5. #define ALEN 3//ACK帧长度   
  6. #define SWP_SEND_TIMEOUT 500//定义超时长度为500ms   
  7. #define LINK "127.0.0.1"//定义要发送的对象   
  8. #define FLAG_ACK_VALID 'a'//定义ACK帧   
  9. #define FLAG_DATA_VALID 'd'//定义数据帧   
  10. #define SUCCESS 1;//定义已经成功收到的消息   
  11.   
  12.   
  13. static void sendSWP(SwpState *state,Msg *frame);//发送函数   
  14. static int deliverSWP(SwpState *state,Msg *frame);//接收并返回ACK函数   
  15.   
  16. //发送   
  17. static void semWait(Semaphore *sendWindowNotFull);//信号量处理(-1)   
  18. static void store_swp_hdr(SwpHdr hdr,char *hbuf);//存储发送的帧头部   
  19. static void msgAddHdr(Msg *frame,char *hbuf);//将头部添加到帧上   
  20. static void msgSaveCopy(char *msg,Msg *frame);//将消息添加到帧上   
  21. static Event evSchedule(Msg *frame,int time);//调用定时器函数   
  22. DWORD WINAPI swpTimeout(LPVOID threadtype);//创建定时器线程   
  23. static void send_socket(char *addr,Msg *frame,int size);//UDP发送   
  24. static void mlisten();//监听数据   
  25. static void msend();//发送数据   
  26. //接收   
  27. static char *msgStripHdr(Msg *frame,int length);//获取帧的头部   
  28. static void load_swp_hdr(SwpHdr *hdr,char *hbuf);//帧头部提取字符串   
  29. static bool swpInWindow(SwpSeqno AckNum,SwpSeqno LAR,SwpSeqno LFS);//判断收到的帧是否在窗口内   
  30. static void evCancel(Event *);//取消超时定时器   
  31. static void msgDestroy(Msg *msg);//释放msg空间   
  32. static void semSignal(Semaphore *sendWindowNotFull);//信号量处理(+1)   
  33. static void prepare_ack(Msg *msg,SwpSeqno n);//组成ACK消息   
  34.   
  35. //全局变量   
  36. HANDLE hlisten;  
  37. HANDLE hsend;  
  38. SwpState *send_state;  
  39. Msg *frame;  
  40. HANDLE Mutex = CreateMutex(NULL,FALSE,NULL);  
  41.   
  42. void main(){  
  43.     //模拟滑动窗口接收和发送过程   
  44.     //初始化SwpState,Msg,数据帧组帧   
  45.     //启动两个线程,模拟收发   
  46.     //监听终止   
  47.     frame=(Msg *)malloc(11*sizeof(Msg));  
  48.     //初始化消息   
  49.     //frame="message";//8个字节的数据   
  50.     //初始化状态   
  51.     send_state=(SwpState *)malloc(sizeof(SwpState));  
  52.     send_state->LAR='0';  
  53.     send_state->LFS='0';  
  54.     send_state->NFE='0';  
  55.     send_state->sendWindowNotFull=CreateSemaphore(NULL,SWS,SWS,NULL);  
  56.     if(send_state->sendWindowNotFull==NULL){  
  57.         printf("CreateSemaphore error ",GetLastError());  
  58.         exit(0);  
  59.     }  
  60.     send_state->hdr.SeqNum='0';//3个字节头部   
  61.     send_state->hdr.AckNum='0';  
  62.     send_state->hdr.Flags='d';  
  63.     for(int i=0;i<SWS;i++){  
  64.         send_state->sendQ[i].msg=(Msg *)malloc(8*sizeof(Msg));  
  65.         send_state->sendQ[i].msg="message";  
  66.         send_state->sendQ[i].timeout=NULL;  
  67.     }  
  68.     for(int i=0;i<RWS;i++){  
  69.         send_state->recvQ[i].msg=(Msg *)malloc(8*sizeof(Msg));  
  70.         send_state->recvQ[i].msg="message";  
  71.         send_state->recvQ[i].recevied=NULL;  
  72.     }  
  73.     //初始化UDP函数   
  74.     WSADATA wsaData;  
  75.     if (WSAStartup(MAKEWORD(2,1),&wsaData)){  
  76.         printf("Winsock initializing fail ");  
  77.         WSACleanup();  
  78.         return;  
  79.     }  
  80.     //建立监听线程   
  81.     hlisten=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) mlisten,NULL,CREATE_SUSPENDED,NULL);  
  82.     ResumeThread(hlisten);  
  83.     if(hlisten==NULL){  
  84.         printf("thread_listen create fail ");  
  85.     }  
  86.     hsend=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) msend,NULL,CREATE_SUSPENDED,NULL);  
  87.     ResumeThread(hsend);  
  88.     if(hsend==NULL){  
  89.         printf("thread_send create fail ");  
  90.     }  
  91.     Sleep(10000);  
  92.     WSACleanup();  
  93. }  
  94. static void msend(){  
  95.     printf("thread_send started ");  
  96.     while(1){  
  97.         sendSWP(send_state,frame);  
  98.     }  
  99.     printf("thread_send quit ");  
  100. }  
  101.   
  102. static void sendSWP(SwpState *state,Msg *frame){  
  103.     struct sendQ_slot *slot;//等待发送   
  104.     char hbuf[HLEN];//附加在帧头部的字符串   
  105.   
  106.     //等待打开发送窗口   
  107.     semWait(&state->sendWindowNotFull);  
  108.     WaitForSingleObject(Mutex,INFINITE);  
  109.     state->hdr.SeqNum=state->LFS++;  
  110.     printf("send %d ",state->hdr.SeqNum);  
  111.     slot=&(state->sendQ[state->hdr.SeqNum % SWS]);  
  112.     store_swp_hdr(state->hdr,hbuf);  
  113.     msgAddHdr(frame,hbuf);  
  114.     msgSaveCopy(slot->msg,frame);  
  115.     slot->timeout=evSchedule(frame,SWP_SEND_TIMEOUT);  
  116.     send_socket(LINK,frame,HLEN+DLEN);  
  117.     ReleaseMutex(Mutex);  
  118. }  
  119.   
  120. static int deliverSWP(SwpState *state,Msg *frame){  
  121.     SwpHdr hdr;  
  122.     char *hbuf;  
  123.     hbuf = msgStripHdr(frame,HLEN);  
  124.     load_swp_hdr(&hdr,hbuf);  
  125.     if(hdr.Flags == FLAG_ACK_VALID){  
  126.             //发送方收到一个ACK,处理ACK帧   
  127.         if(swpInWindow(hdr.AckNum,state->LAR,state->LFS)){  
  128.                 do{  
  129.                     WaitForSingleObject(Mutex,INFINITE);  
  130.                     printf("send get ack %d ",hdr.AckNum);  
  131.                     struct sendQ_slot *slot;  
  132.                     slot=&state->sendQ[state->LAR++ % SWS];  
  133.                     evCancel(&slot->timeout);  
  134.                     //msgDestroy(slot->msg);   
  135.                     semSignal(&state->sendWindowNotFull);  
  136.                     ReleaseMutex(Mutex);  
  137.                 }while(state->LAR==hdr.AckNum);  
  138.         }  
  139.     }  
  140.     if(hdr.Flags == FLAG_DATA_VALID){  
  141.             //接收到数据帧,处理数据帧   
  142.         WaitForSingleObject(Mutex,INFINITE);  
  143.         struct recvQ_slot *slot;  
  144.         slot=&state->recvQ[hdr.SeqNum % RWS];  
  145.         if(!swpInWindow(hdr.SeqNum,state->NFE,state->NFE+RWS-1)){  
  146.             ReleaseMutex(Mutex);  
  147.             return SUCCESS;  
  148.         }  
  149.         msgSaveCopy(slot->msg,frame);  
  150.         slot->recevied=TRUE;  
  151.         if(hdr.SeqNum==state->NFE){  
  152.             Msg *m=(Msg *)malloc(3*sizeof(Msg));  
  153.             while(slot->recevied){  
  154.                 //deliver(HLP,&slot->msg)//传向上层   
  155.                 printf("receive get data %d ",hdr.SeqNum);  
  156.                 printf("%s ",slot->msg);  
  157.                 //msgDestroy(slot->msg);   
  158.                 slot->recevied=FALSE;  
  159.                 slot=&state->recvQ[state->NFE++ % RWS];  
  160.             }  
  161.             prepare_ack(m,state->NFE-1);  
  162.             send_socket(LINK,m,ALEN);  
  163.             msgDestroy(m);  
  164.         }  
  165.         ReleaseMutex(Mutex);  
  166.     }  
  167.     return SUCCESS;  
  168. }  
  169.   
  170. static void semWait(Semaphore *sendWindowNotFull){  
  171.     DWORD   wait_for_semaphore;  
  172.     wait_for_semaphore  =  WaitForSingleObject(*sendWindowNotFull,-1);  
  173. }  
  174.   
  175. static void store_swp_hdr(SwpHdr hdr,char *hbuf){  
  176.     hbuf[0]=hdr.SeqNum;  
  177.     hbuf[1]=hdr.AckNum;  
  178.     hbuf[2]=hdr.Flags;  
  179. }  
  180.   
  181. static void msgAddHdr(Msg *frame,char *hbuf){  
  182.     frame[0]=hbuf[0];  
  183.     frame[1]=hbuf[1];  
  184.     frame[2]=hbuf[2];  
  185. }  
  186.   
  187. static void msgSaveCopy(char *msg,Msg *frame){  
  188.     int j=0;  
  189.     for(int i=3;i<11;i++){  
  190.         frame[i]=msg[j];  
  191.         j++;  
  192.     }  
  193. }  
  194.   
  195. static Event evSchedule(Msg *frame,int time){  
  196.     TimeOutType *timetype=(TimeOutType *)malloc(sizeof(TimeOutType));//超时线程参数   
  197.     timetype->time=time;  
  198.     for(int i=0;i<11;i++){  
  199.         timetype->frame[i]=frame[i];  
  200.     }  
  201.     //创建定时器线程   
  202.     DWORD targetThreadID;  
  203.     HANDLE Timer=CreateThread(NULL,0,swpTimeout,timetype,CREATE_SUSPENDED,NULL);  
  204.     ResumeThread(Timer);  
  205.     if(Timer==NULL){  
  206.         printf("thread_timeout create fail ");  
  207.     }  
  208.     return Timer;  
  209. }  
  210.   
  211. DWORD WINAPI swpTimeout(LPVOID threadtype){  
  212.     printf("thread_timeout started ");  
  213.     TimeOutType *timetype=(TimeOutType *)threadtype;  
  214.     int time=timetype->time;  
  215.     Msg *frame;  
  216.     DWORD result=1;  
  217.     frame=timetype->frame;  
  218.     SetTimer(NULL,0,time,NULL);  
  219.   
  220.     MSG msg;  
  221.     BOOL bRet;  
  222.   
  223.     while (TRUE)  
  224.     //该循环捕捉定时器消息      
  225.     {  
  226.         bRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);  
  227.         if (bRet ==  - 1){  
  228.             // handle the error and possibly exit   
  229.         }  
  230.         else if (bRet && msg.message == WM_TIMER){//定时器   
  231.             //处理超时事件   
  232.             printf("send重发%d ",frame[0]);  
  233.             send_socket(LINK,frame,HLEN+DLEN);//超时重发   
  234.         }  
  235.         else{  
  236.             TranslateMessage(&msg);  
  237.             DispatchMessage(&msg);  
  238.         }  
  239.     }  
  240.     printf("thread_timeout_quit");  
  241.     return result;  
  242. }  
  243.   
  244. static void mlisten(){  
  245.     printf("thread_listen started ");  
  246.     SOCKET socket1;  
  247.     struct sockaddr_in local;  
  248.     struct sockaddr_in from;  
  249.     int fromlen =sizeof(from);  
  250.     local.sin_family=AF_INET;  
  251.     local.sin_port=htons(8808); ///监听端口   
  252.     local.sin_addr.s_addr=INADDR_ANY; ///本机   
  253.   
  254.     socket1=socket(AF_INET,SOCK_DGRAM,0);  
  255.     bind(socket1,(struct sockaddr*)&local,sizeof(local));  
  256.     while (1){  
  257.         char buffer[11]={0};  
  258.         if (recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR){  
  259.                 deliverSWP(send_state,buffer);  
  260.         }  
  261.     }  
  262.     closesocket(socket1);  
  263.     printf("listen thread quit ");  
  264. }  
  265.   
  266. static void send_socket(char *addr,Msg *frame,int size){  
  267.     //UDP发送函数   
  268.     SOCKET socket1;  
  269.   
  270.     struct sockaddr_in server;  
  271.     int len =sizeof(server);  
  272.     server.sin_family=AF_INET;  
  273.     server.sin_port=htons(8808); ///server的监听端口   
  274.     server.sin_addr.s_addr=inet_addr(LINK); ///server的地址   
  275.   
  276.     socket1=socket(AF_INET,SOCK_DGRAM,0);  
  277.      if (sendto(socket1,frame,sizeof(frame),0,(struct sockaddr*)&server,len)!=SOCKET_ERROR){  
  278.   
  279.      }  
  280.      closesocket(socket1);  
  281. }  
  282.   
  283. static char *msgStripHdr(Msg *frame,int length){  
  284.     char *result=(char *)malloc(sizeof(char));  
  285.     for(int i=0;i<length;i++){  
  286.         result[i]=frame[i];  
  287.     }  
  288.     return result;  
  289. }  
  290.   
  291. static void load_swp_hdr(SwpHdr *hdr,char *hbuf){  
  292.     hdr->SeqNum=hbuf[0];  
  293.     hdr->AckNum=hbuf[1];  
  294.     hdr->Flags=hbuf[2];  
  295. }  
  296.   
  297. static bool swpInWindow(SwpSeqno seqno,SwpSeqno min,SwpSeqno max){  
  298.     SwpSeqno pos,maxpos;  
  299.     pos=seqno-min;  
  300.     maxpos=max-min+1;  
  301.     return pos<maxpos;  
  302. }  
  303.   
  304. static void evCancel(Event *thread){  
  305.     TerminateThread(*thread,0);  
  306.     printf("thread_timeout quit ");  
  307. }  
  308.   
  309. static void msgDestroy(Msg *msg){  
  310.     free(msg);  
  311. }  
  312.   
  313. static void semSignal(Semaphore *sendWindowNotFull){  
  314.     if(!ReleaseSemaphore(*sendWindowNotFull,1,NULL)){  
  315.         printf("ReleseSemphore error ");  
  316.         exit(0);  
  317.     }  
  318. }  
  319.   
  320. static void prepare_ack(Msg *m,SwpSeqno n){  
  321.     //ack组帧   
  322.     m[0]=NULL;  
  323.     m[1]=n;  
  324.     m[2]='a';  
  325. }  
原文地址:https://www.cnblogs.com/langqi250/p/3296877.html