顺序表的企业级应用案例

高并发 WEB 服务器中顺序表的应用 高性能的 web 服务器 Squid 每秒可处理上万并发的请求,从网络连接到服务器的客 户端与服务器端在交互时会保持一种会话(和电话通话的场景类似)。服务器端为了管 理好所有的客户端连接,给每个连接都编了一个唯一的整数编号,叫做文件句柄,简称 fd
为了防止某些恶意连接消耗系统资源,当某个客户端连接超时(在设定的一定时 间内没有发送数据)时,服务器就需要关闭这些客户端的连接 具体实现方案:

  1. 当有新的请求连到服务器时,如果经过服务器频率限制模块判断,貌似恶意连 接,则使用顺序表来保存此连接的超时数据,超时值使用时间戳来表示,时间戳是指格林 威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒(相当于北京时间 1970 年 01 月 01 日 08 时 00 分 00 秒)起至现在的总秒数,其结构体定义如下: typedef struct { int fd ; time_t timeout; // 使用超时时刻的时间戳表示}ConnTimeout;
  2. 服务器程序每隔一秒钟扫描一次所有的连接,检查是否超时,如果存在超时的 连接,就关闭连接,结束服务,同时将顺序表中的记录清除!
    代码:webServer.h
#pragma once
#include<time.h>
#define MAX_SIZE 1000
typedef struct {
    
    
	int fd;
	time_t timeout;
}ConnTimeout;
typedef struct {
    
    
	ConnTimeout* elems; // 顺序表的基地址 
	int length; // 顺序表的长度
	int size; // 顺序表的空间 
}TimeoutSqList;
//顺序表的接口
bool initList(TimeoutSqList& L);
bool listAppend(TimeoutSqList& L, ConnTimeout e);
bool listDelete(TimeoutSqList& L, int i);
void destroyList(TimeoutSqList& L);
void listPrint(TimeoutSqList& L);

timeoutSqList.cpp

#include"webServer.h"
#include<iostream>
using namespace std; 
bool initList(TimeoutSqList& L) {
    
    
	L.elems = new ConnTimeout[MAX_SIZE];
	if (!L.elems)
		return false;
	L.length = 0;
	L.size = MAX_SIZE;
	return true;
}
bool listAppend(TimeoutSqList& L, ConnTimeout e) {
    
    
	if (L.length == L.size)return false;
	L.elems[L.length] = e;
	L.length++;
	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 destroyList(TimeoutSqList& L) {
    
    
	if (L.elems) delete[]L.elems;
	L.length = 0;
	L.size = 0;
}
void listPrint(TimeoutSqList& L) {
    
    
	cout << "当前:" << L.size << ",已保存元素的个数 length:" << L.length << endl;
	for (int i = 0;i < L.length;i++) {
    
    
		cout << "fd:" << L.elems[i].fd << ",timeout:" << L.elems[i].timeout << endl;
	}
	cout << endl;
}

主.cpp

#include<iostream>
#include<time.h>
#include<Windows.h>
#include<stdio.h>
#include"webServer.h"
using namespace std;
/*
	感想:此时实验仅检测60s,且是1s一检测,
	首先通过模拟用户访问,把一些用户数据放到顺序表中
	在根据访问时间,检测是否是恶意访问.
*/
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);
	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);
		time(&now);
	} while (now < end);
	system("pause");
	return 0;
}
void checkTimeouts(TimeoutSqList& list, time_t now) {
    
    
	int fd, i;
	cout << "检查超时fd。。。。。。。。。。"<<endl;
	for (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--;
	}
}
		***

1s一检测的小技巧: 因为用Sleep服务器是不工作的 所以通过使用时间戳,然后定义一个变量t,获取当前的时间 再不断循环,循环中获取时间,说过现在的时间比定义的t大于1 就说明是超过1秒了,这样if语句中就可以判断,然后在重新赋值 给t,再判断。


猜你喜欢

转载自blog.csdn.net/weixin_49324123/article/details/111082389
今日推荐