zoukankan      html  css  js  c++  java
  • 基于滑动窗口协议写的程序(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. }  
  • 相关阅读:
    Jmeter请求头中添加了Authorization,但是在结果树里面的headers中显示没有获取到token
    linux(1):VMware虚拟软件下安装centos6.8
    Appium+python自动化环境搭建(小白适用)
    面试题:get和post的本质区别
    用python实现不同格式99乘法表输出
    冒泡排序:从数学逻辑到代码呈现
    给你一句话的需求,如何拆分测试点来设计测试案例
    Linux下基于Xampp的TestLink的安装部署
    linux环境下完成jenkins的环境搭建
    工作中遇到的小问题总结
  • 原文地址:https://www.cnblogs.com/langqi250/p/3296877.html
Copyright © 2011-2022 走看看