高并发 WEB 服务器中顺序表的应用
高性能的 web 服务器 Squid 每秒可处理上万并发的请求,从网络连接到服务器的客户端与服务器端在交互时会保持一种会话(和电话通话的场景类似)。服务器端为了管理好所有的客户端连接,给每个连接都编了一个唯一的整数编号,叫做文件句柄,简称fd
为了防止某些恶意连接消耗系统资源,当某个客户端连接超时(在设定的一定时间内没有发送数据)时,服务器就需要关闭这些客户端的连接
具体实现方案:
.当有新的请求连到服务器时,如果经过服务器频率限制模块判断,貌似恶意连接,则使用顺序表来保存此连接的超时数据,超时值使用时间戳来表示,时间戳是指格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒(相当于北京时间1970 年01 月01日08 时 00 分 00 秒)起至现在的总秒数
c语言获得当前时间
#include "stdio.h"
#include "time.h"
#include "windows.h"
int main(){
time_t now_time;
time(&now_time);
printf("当前时间%d\n", now_time);
// 获取2000毫秒以后
Sleep(2000);
time(&now_time);
printf("当前时间%d\n", now_time);
return 0;
}
webserver.h
#ifndef SEQ_LIST_WEBSERVER_H
#define SEQ_LIST_WEBSERVER_H
#include <ctime>
#define max_size 100
//定义结构体,存储超时的时间
typedef struct {
int td;
// 超时的时刻
time_t time_out;
}ConnTimeout;
typedef struct {
// 顺序表的基地址
ConnTimeout *data;
// 长度
int length;
// 大小
int size;
}TimeoutSqList;
//顺序表的接口
bool InitList(TimeoutSqList &L);
bool AppendList(TimeoutSqList &L, ConnTimeout e);
bool DeleteList(TimeoutSqList &L, int pos);
void DisplayList(TimeoutSqList &L);
#endif
timeoutSeqList.h
#include "stdio.h"
#include "webserver.h"
bool InitList(TimeoutSqList &L){
L.data = new ConnTimeout [max_size];
if(!L.data){
return false;
}
L.length = 0;
L.size = max_size;
return true;
}
bool AppendList(TimeoutSqList &L, ConnTimeout value){
if(L.length == max_size){
return false;
}
L.data[L.length] = value;
L.length++;
return true;
}
bool DeleteList(TimeoutSqList &L, int pos){
// 同样检查
if(pos < 0 || pos > L.length){
return false;
}
// 删除了肯定要减
L.length--;
// 往前移动
for(int i = pos; i < L.length; i++){
L.data[i -1] = L.data[i];
}
return true;
}
void DisplayList(TimeoutSqList &L){
for(int i = 0; i < L.length; i++){
printf("data[%d]=%d ", L.data[i].td, L.data[i].time_out);
}
printf("\n");
}
简单逻辑
#include "timeoutSeqList.h"
int main(){
time_t now_time, end_time;
TimeoutSqList List;
time(&now_time);
// 假设60秒后退出循环
end_time = now_time + 60;
InitList(List);
// 模拟频率限制模块,增加恶意连接到顺序表
for(int i = 0; i < 10; i++){
ConnTimeout e;
e.td = i;
e.timeout = now_time + 5 + 2 * i;
AppendList(List, e);
}
DisplayList(List);
/*
do{
time(&now_time);
} while (now_time < end_time);
*/
return 0;
}
完整的main.cpp
#include "timeoutSeqList.h"
#include "windows.h"
void CheckTimeOuts(TimeoutSqList &List, time_t now_time){
int fd, count;
printf("检查超时\n");
for(count = 0; count < List.length; count++){
if(List.data[count].time_out > now_time) {
continue;
}else{
// 超时,清理连接
fd = List.data[count].td;
printf("连接%d已经超时,删除\n", fd);
DeleteList(List, count);
count--;
}
}
}
int main(){
time_t now_time, end_time;
// 上一次的处理时间
time_t last_timeout;
TimeoutSqList List;
time(&now_time);
// 假设60秒后退出循环
end_time = now_time + 60;
last_timeout = now_time;
InitList(List);
// 模拟频率限制模块,增加恶意连接到顺序表
for(int i = 0; i < 10; i++){
ConnTimeout e;
e.td = i;
e.time_out = now_time + 5 + 2 * i;
AppendList(List, e);
}
// DisplayList(List);
do{
// 假设过了一秒钟
if(double (last_timeout) + 0.999 < double (now_time)){
CheckTimeOuts(List, now_time);
last_timeout = now_time;
}
// 休眠一下
Sleep(10);
time(&now_time);
} while (now_time < end_time);
return 0;
}