正好有一个大作业关于用socket实现滑动窗口协议,所以写了一个,模拟接收方与发送方窗口都是2,用两个线程实现。
下面是代码,注释的比较详细了。
socket_udp.h
#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
#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 le