先建立一个顺序表的头文件 webServer.h
#ifndef _WEB_SERVER_H_
#define _WEB_SERVER_H_
#include <iostream>
#include <time.h>
#include <Windows.h>
#include <time.h>
#define MAX_SIZE 1000
typedef struct
{
int fd; //顺序表用户的ID
time_t timeout; //使用超时时刻的时间戳表示
}ConnTimeout;
typedef struct
{
ConnTimeout* elems; //顺序表的基址
int length; //顺序表的长度
int size; //顺序表的空间
}TimeoutSqList;
#endif // !_WEB_SERVER_H_
//顺序表的接口
bool initList(TimeoutSqList& L);
bool listAppend(TimeoutSqList& L, ConnTimeout e);
bool listDelete(TimeoutSqList& L, int i);
void listPrint(TimeoutSqList& L);
void destroyList(TimeoutSqList& L);
接下来是顺序表接口的具体实现 timeoutSqlist.cpp
#include "webServer.h"
#include <iostream>
using namespace std;
bool initList(TimeoutSqList & L) //构造一个空的顺序表L
{
L.elems = new ConnTimeout[MAX_SIZE]; //为顺序表分配Maxsize 个空间
if (!L.elems) return false; //存储分配失败
L.length = 0; //空表长度为0
L.size = MAX_SIZE;
return true;
}
bool listAppend(TimeoutSqList & L, ConnTimeout e)
{
if (L.length == MAX_SIZE) return false; //存储空间已满
L.elems[L.length] = e;
L.length++; //表长增1
return true;
}
bool listDelete(TimeoutSqList& L, int i)
{
if (i < 0 || i >= L.length) return false; //不合法
if (i == L.length - 1) {//删除最后一个元素,直接删除
L.length--;
return true;
}
for (int j = i; j < L.length - 1; j++) {
L.elems[j] = L.elems[j + 1]; //被删除元素之后的元素前移
}
L.length--;
return true;
}
void listPrint(TimeoutSqList& L)
{
cout << "当前" << L.size << ", 已保存元素个数length: " <<L.length << endl;
for (int j = 0; j <= L.length - 1; j++) {
cout << "fd:" << L.elems[j].fd << ",timeout: " << L.elems[j].timeout << endl;
}
cout << endl;
}
void destroyList(TimeoutSqList& L)
{
if (L.elems) delete[]L.elems;//释放存储空间
L.length = 0;
L.size = 0;
}
最后是main函数实现具体方法
#include "webServer.h"
using namespace std;
//检查连接超时后删除顺序表元素的函数
static void checkTimeouts(TimeoutSqList& list, time_t now);
int main()
{
time_t now, end;
time_t last_timeout;
TimeoutSqList list;
time(&now);//当前时间
end = now + 60;//60s 后退出循环
last_timeout = now;
initList(list);
//1.模拟频率限制模块通过判断分析,增加恶意连接到顺序表中
for (int i = 0; i < 10; i++)
{
ConnTimeout e; //用户
e.fd = i;
e.timeout = now + 5 + 2 * i;//设定超时时间
listAppend(list, e);//把元素添加进顺序表
}
listPrint(list);
do
{
if (last_timeout + 0.999 < now)
{
checkTimeouts(list, now);//检查超时的连接
last_timeout = now;
}
Sleep(10);//休眠0.01秒
time(&now);//不断取当前时间
} while (now < end);//结束时间60秒
return 0;
}
void checkTimeouts(TimeoutSqList& list, time_t now)
{
int fd, i;
cout << "检查超时fd... ...\n";
for (int i = 0; i < list.length; i++)
{
if (list.elems[i].timeout > now)
{
continue;
}
//超时,清理链接
fd = list.elems[i].fd;
//关闭连接
printf("连接[fd=%d]已经超时,关闭连接!\n", fd);
//删除顺序表中的元素
listDelete(list, i);
i--;//删除元素后元素会移动,所以i不用++
}
}