数据结构之顺序表,高并发服务器顺序表的应用

高性能的web服务器Squit每秒可处理上万并发的请求,从网络连接到服务器的客户端与服务端在交互时会保持一种(和电话通话的场景类似)。服务器端为了管理好所有的客户端连接,给每个连接都编了一个唯一的整数编号,叫做文件句柄,简称fd。为了防止某些恶意连接消耗系统资源,当某个客户端连接超时(在设定的一定时间内没有发送数据)时,服务器就需要关闭这些客户端的连接
实现方案:
1.当有新的请求连到服务器时,如果经过服务器频率限制块判断,貌似恶意连接,则使用顺序表来保持此连接的超时数据,超时值使用时间戳来表示,时间戳是指格林威治时间1970年01月01日00时00分00秒(相当于北京时间1970年01月01日00时00分00秒)起至现在的总秒数。
2.服务器程序每隔一秒扫描一次所有的连接,检查是否超时,如果存在超时的连接,就关闭连接,结束服务,同时将顺序表中的记录清除!
//webServer.h

//开发工具:vs2019
//qq:1020785391
//作者:王杰
#pragma once
#include <time.h>

#define MAX_SIZE 100

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 listDestory(TimeoutSqList& L);
void listPrint(TimeoutSqList& L);

//webServer.cpp

#include <iostream>
#include <windows.h>
#include "webServer.h"

using namespace std;
static void checkTimeouts(TimeoutSqList& L, time_t now);

int main()
{
	time_t now, end;		//声明时间戳
	time_t last_timeout;
	TimeoutSqList L;

	time(&now);
	end = now + 60;		//60s后,退出循环
	last_timeout = now;
	initList(L);

	//1.模拟频率限制模块通过判断分析,增加恶意连接到顺序表
	for (int i = 0; i < 10; i++)
	{
		ConnTimeout e;
		e.fd = i;
		e.timeout = now + 5 + 2*i;
		listAppend(L,e);
	}
	listPrint(L);

	do 
	{
		//控制每一秒钟检查一次
		if (last_timeout + 0.999 < now)
		{
			checkTimeouts(L, now);
			last_timeout = now;
		}
		Sleep(10);
		time(&now);
	} while (now < end);

	system("pause");
	listDestory(L);
	return 0;
}

void checkTimeouts(TimeoutSqList& L, time_t now)
{
	int fd, i;
	cout << "检查超时fd... ...\n";
	for (int i=0;i<L.length;i++)
	{
		if (L.elems[i].timeout > now)
		{
			continue;
		}
		//超时,清理连接
		fd = L.elems[i].fd;
		//关闭连接
		cout << "连接[fd=" << fd << "]已经超时,关闭连接" << endl;
		//删除
		listDelete(L, i);
		//i必须减1,不然容易直接跳过被删元素的后1个元素,******************
		i--;
	}
}

//timeoutSqList.cpp

#include <iostream>
#include "webServer.h"

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 - 1) return false;
	if (i == L.length--)
	{
		L.length--;
		return true;
	}
	for (int j = i; i < L.length-1; j++)
	{
		L.elems[i] = L.elems[i + 1];
	}
	L.length--;
	return true;
}

void listDestory(TimeoutSqList& L)
{
	if (L.elems)
	{
		delete L.elems;
		L.elems = NULL;
	}
	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;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值