一、最大连接数的限制

概念

这是指服务器可以同时接收的最大连接数,防止服务器压力过大而在应用层进行的限制。

实现

总体思路:将当前连接数保存于变量num_clients变量中,然后与配置项numble_max_clients进行比较,如果超过了就不让登录,当一个客户登录的时候num_clents加1,当一个客户退出的时候,num_clients减1。

1.一旦服务器端与客户端经过三次握手建立连接之后,服务端就需要创建进程为其服务,此时,将连接数加1。

//来了一个新的客户端,需要创建子进程出来
++s_children;
//当前连接数等于子进程数
sess.num_clients = s_children;

2.然后在负责服务的子进程中进行最大连接数的判断

如果当前连接数超过了最大连接数,那么就要退出当前子进程。

//连接数的判定
void check_limits(session_t *sess)
{//最大连接数配置项是否开启并且当前连接数超过了最大连接数if (tunable_max_clients > 0 && sess->num_clients > tunable_max_clients) {ftp_reply(sess, FTP_TOO_MANY_USERS, "There are too many connected users, please try later.");//退出当前子进程exit(EXIT_FAILURE);}//最大连接数没有超过上限的情况下,再检查ip的连接数是否超过上限if (tunable_max_per_ip > 0 && sess->num_this_ip > tunable_max_per_ip) {ftp_reply(sess, FTP_IP_LIMIT, "There are too many connections from your internet address.");exit(EXIT_FAILURE);}
}

3.负责服务客户端的子进程退出连接后,父进程进行后续处理。

父进程是专门用于处理客户端连接的,父进程会注册SIGCHLD信号,在信号函数中将连接数进行减一操作。

//子进程退出时候的信号处理函数
signal(SIGCHLD, handle_sigchld);
void handle_sigchld(int sig)
{// 当一个客户端退出的时候,那么该客户端对应ip的连接数要减1,// 处理过程是这样的,首先是客户端退出的时候,// 父进程需要知道这个客户端的ip,这可以通过在s_pid_ip_hash查找得到,pid_t pid;while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {--s_children;//通过pid找到ipunsigned int *ip = hash_lookup_entry(s_pid_ip_hash, &pid, sizeof(pid));if (ip == NULL) {continue;}drop_ip_count(ip);//进程退出,进程和ip的表项就没有意义了hash_free_entry(s_pid_ip_hash, &pid, sizeof(pid));}}

二、每IP连接数的限制

概念

是在说某个IP能够连接的最大个数。如果达到了每IP的最大连接数的数量,即使没有达到总的最大连接数的限制,那么也会中断当前连接。

实现

维护两个哈希表

static hash_t *s_ip_count_hash   ip与对应连接数的哈希表

static hash_t *s_pid_ip_hash        进程与ip对应的哈希函数表

将当前ip的连接数保存在变量num_this_ip中,然后与配置项tumable_max_per_ip进行比较,如果超过了就不让登录,当一个客户登录的时候,要在s_ip_count_hash这个哈希表中更新对应的表项,即该ip对应的连接数要加1,如果这个表项还不存在,要在表中添加一条记录,并将ip对应的连接数置1,当一个客户端退出的时候,那么该客户端对应ip的连接数减1,处理过程是这样的,首先是客户端退出的时候,父进程需要知道这个客户的ip,这可以通过在s_pid_ip_hash这个哈希表中查找得到,得到了ip进而我们就可以在s_ip_count_hash表中找到对应的连接数,进而进行减1操作。

因为子进程的退出的时候,父进程要减少该进程对应ip的连接数,但是父进程只能知道是哪个进程退出了,不能知道是哪个ip的连接数需要减一,所以进程与ip对应的哈希函数表是必要的。

1.建立两个哈希表

//创建hash表,256是桶的个数,hash_fun是哈希函数
s_ip_count_hash = hash_alloc(256, hash_func);
s_pid_ip_hash = hash_alloc(256, hash_func);
//哈希函数
unsigned int hash_func(unsigned int buckets, void *key)
{unsigned int *number = (unsigned int*)key;//void*转换为unsigned int*//返回桶号return (*number) % buckets;
}

2.连接建立之后,s_ip_count_hash的更新

当客户端的一个连接过来之后,可以由accept得到对等方的地址,然后对ip和连接数的哈希表进行更新操作。如果之前有这个ip,连接数加1;如果之前没有这个ip,插入一个ip和连接数为1的表项。

//返回当前ip的连接数,进行加1操作
unsigned int handle_ip_count(void *ip)
{// 当一个客户登录的时候,要在s_ip_count_hash更新这个表中的对应表项,// 即该ip对应的连接数要加1,如果这个表项还不存在,要在表中添加一条记录,// 并且将ip对应的连接数置1。unsigned int count;unsigned int *p_count = (unsigned int *)hash_lookup_entry(s_ip_count_hash,ip, sizeof(unsigned int));//表明该ip是第一次连接if (p_count == NULL) {count = 1;//插入一个表项hash_add_entry(s_ip_count_hash, ip, sizeof(unsigned int),&count, sizeof(unsigned int));}//表项已经存在,更新对应的连接数else {count = *p_count;++count;*p_count = count;}return count;
}

3.连接建立之后,s_pid_ip_hash的更新

插入进程和ip的表项,这是在父进程中进行的

//添加进程和ip的对应关系,这里的进程是子进程
hash_add_entry(s_pid_ip_hash, &pid, sizeof(pid),&ip, sizeof(unsigned int));

4.在子进程中进行连接数的判断

先判断总的最大连接数,如果超过最大连接数就要退出当前子进程;再判断是否超过每ip的最大连接数,如果超过最大连接数就要退出当前子进程。

//连接数的判定
void check_limits(session_t *sess)
{//最大连接数配置项是否开启并且当前连接数超过了最大连接数if (tunable_max_clients > 0 && sess->num_clients > tunable_max_clients) {ftp_reply(sess, FTP_TOO_MANY_USERS, "There are too many connected users, please try later.");//退出当前子进程exit(EXIT_FAILURE);}//最大连接数没有超过上限的情况下,再检查ip的连接数是否超过上限if (tunable_max_per_ip > 0 && sess->num_this_ip > tunable_max_per_ip) {ftp_reply(sess, FTP_IP_LIMIT, "There are too many connections from your internet address.");exit(EXIT_FAILURE);}
}

5.子进程退出之后,父进程进入sigchld信号处理函数

首先在哈希表s_pid_ip_hash中根据进程号获得ip

void handle_sigchld(int sig)
{// 当一个客户端退出的时候,那么该客户端对应ip的连接数要减1,// 处理过程是这样的,首先是客户端退出的时候,// 父进程需要知道这个客户端的ip,这可以通过在s_pid_ip_hash查找得到,pid_t pid;while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {--s_children;//通过pid找到ipunsigned int *ip = hash_lookup_entry(s_pid_ip_hash, &pid, sizeof(pid));if (ip == NULL) {continue;}drop_ip_count(ip);//进程退出,进程和ip的表项就没有意义了hash_free_entry(s_pid_ip_hash, &pid, sizeof(pid));}}

然后将该ip的连接数减1,如果ip数减为0,那么将该ip和连接数的对应表项删除。

//减1操作
void drop_ip_count(void *ip)
{// 得到了ip进而我们就可以在s_ip_count_hash表中找到对应的连接数,进而进行减1操作。unsigned int count;unsigned int *p_count = (unsigned int *)hash_lookup_entry(s_ip_count_hash,ip, sizeof(unsigned int));if (p_count == NULL) {return;}count = *p_count;if (count <= 0) {return;}--count;*p_count = count;if (count == 0) {//可以删除表项了hash_free_entry(s_ip_count_hash, ip, sizeof(unsigned int));}
}

进程退出之后,进程和ip的表项也就没有意义了,删除。

最大连接数与每ip连接数的限制相关推荐

  1. nginx 和php连接数,nginx限制ip连接数和带宽

    搜索热词 今天有个人问我,Nginx怎么限制ip连接数,突然想不起来了,年龄大了,脑子不怎么好使了.还要看一下配置才想起了.那个人又问我,你测试过的吗?一下子把我问蒙了,我真没测试过了,也不知道启作用 ...

  2. linux 防火墙 限速,linux iptables限速及限制每IP连接数

    第一步:建立adsl连接,在系统设置--网络设置处有.在图形界面下很容易搞定. 第二步:打开IP转发和伪装(也就是路由与NAT) 1.作为根用户打开/etc/sysconfig/network文件,在 ...

  3. (转)Linux下apache限速和限制同一IP连接数的实现

    单位有一台DELL的服务器,4核双CPU,4G内存,1TB的存储空间,闲来无事,申请了域名http://www.zxzy123.cn,做了个网站,本以为用这样的配置做个下载站是绰绰有余了,没想到上线没 ...

  4. linux网络被限制网速,linux iptables限速及限制每IP连接数

    第一步:建立adsl连接,在系统设置--网络设置处有.在图形界面下很容易搞定. 第二步:打开IP转发和伪装(也就是路由与NAT) 1.作为根用户打开/etc/sysconfig/network文件,在 ...

  5. Windows XP SP3增强补丁 V1.3 破解uxtheme.dll和TCP/IP连接数的破解

    下载地址 简介:Windows XP SP3的下载已经提供了,安装了,体验了,感觉没什么太大变化.当然,安装SP3后,对我来说需要做的事情很多,比如破解uxtheme.dll加载第三 方系统主题:以前 ...

  6. linux 限制ip速度,linux iptables限速及限制每IP连接数

    第一步:建立adsl连接,在系统设置--网络设置处有.在图形界面下很容易搞定. 第二步:打开IP转发和伪装(也就是路由与NAT) 1.作为根用户打开/etc/sysconfig/network文件,在 ...

  7. Windows XP SP2 TCP/IP连接数的查看与修改

    众所周知,为了防范蠕虫病毒的传播和攻击,Windows XP SP2将并发线程最多限制为10个.SP2利用Messages动态链接库,来实时监控每个进程的并发线程数目,一旦它发现某进程的线程数超过10 ...

  8. Linux查看网络连接数,统计网络连接数(netstat、Apache连接数)

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat|grep -i "80"|wc -l 2)统计httpd协 ...

  9. 数据库MySQL最大连接数、最大活跃连接数、最大并发数、并发会话数区别

    这里写自定义目录标题) 数据库MySQL最大连接数.最大活跃连接数.最大并发数.并发会话数区别 最大连接数:基于IP建立连接数. 最大活跃连接/并发连接/并发会话: 最大活跃连接是并发连接数,但和并发 ...

最新文章

  1. R语言包_manipulate
  2. 删除同目录下面txt文件(利用os,fnmacth模块)
  3. 现在离开哈尔滨需要做核酸检测吗?
  4. 敏捷项目管理之计划扑克游戏
  5. 【ODBC】ODBC连接数据库详细说明
  6. libusb 串口 android,libusb 根据设备的serialnumber来打开
  7. php imagick 取得psd缩略图,php实现在新浪云中使用imagick生成缩略图并上传的方法...
  8. HDU 6080 2017百度之星程序设计大赛 - 资格赛
  9. arcgis制图汇总
  10. android category 讲解
  11. 国潮复兴——从红旗H9看HMI设计中的东方美学
  12. HTTP 503 错误 – 服务不可用 (Service unavailable)
  13. Go语言:go-redis客户端设置过期时间相关命令Expire,ExpireAt,TTL的用法示例
  14. 实时头发-面部皮肤分割与人脸肤色分类
  15. 红帽Linux重置root密码
  16. 多重循环(图形打印2)-C语言
  17. 40 张图带你搞懂 TCP 和 UDP,android软件开发教程
  18. 基于PHP实现一个简单的在线聊天功能
  19. 产品读书《联盟:互联网时代的人才变革》
  20. 百度看重日本商机 与雅虎日本进行合作

热门文章

  1. Python 10个优雅的写法,你会吗?
  2. java学习中常见比较模糊的部分
  3. MVC、MVVM、MVP
  4. Scratch软件编程等级考试一级——201909
  5. android 错误中英互译,中英文翻译器应用的官方Android版本v3.1.1
  6. 计算机领域 世界级难题,“电脑垃圾”——一个世界性新难题阅读答案
  7. React:安装配置使用scss
  8. python画太极八卦图_CAD怎么画出八卦图? cad画完整太极八卦图的教程
  9. 刨根问底:MySQL索引篇之千万级数据实战测试
  10. pandas相关性分析的三种方法