高并发 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;
}

顺序表应用_#include

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;
}

顺序表应用_顺序表_02

完整的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;
}

顺序表应用_List_03