miniftp项目总结(八)

最大连接数的限制
在session结构体重增加一个num_clients成员,在主线程序中,每当来一个客户端就使num_clients++。子进程在开启会话前要进行最大连接数限制的检查,只有小于最大连接数的限制才开启会话。那么子进程退出的时候如何对num_clients进行维护呢?

void check_limits(session_t *sess)
{
	if(sess->num_clients > tunable_max_clients)
	{
		//421 There are too many connected users, please try later.
		ftp_reply(sess, FTP_TOO_MANY_USERS, "There are too many connected users, please try later.");
		exit(EXIT_FAILURE);
	}
}

每IP数登录的限制
要实现每IP数登录的限制,需要实现两个hash表:ip–count表和pid–ip表
实现哈希表:
hash.h

#ifndef _HASH_H_
#define _HASH_H_

typedef struct hash hash_t;
typedef unsigned int (*hashfunc_t)(unsigned int, void*);

hash_t* hash_alloc(unsigned int buckets, hashfunc_t hash_func);
void* hash_lookup_entry(hash_t *hash, void* key, unsigned int key_size);
void hash_add_entry(hash_t *hash, void *key, unsigned int key_size,
	void *value, unsigned int value_size);
void hash_free_entry(hash_t *hash, void *key, unsigned int key_size);

#endif

hash.c

#include"hash.h"

#include "hash.h"
#include "common.h"
#include <assert.h>

typedef struct hash_node 
{
	void *key;
	void *value;
	struct hash_node *prev;
	struct hash_node *next;
} hash_node_t;


struct hash 
{
	unsigned int buckets;
	hashfunc_t hash_func;
	hash_node_t **nodes;
};

hash_node_t** hash_get_bucket(hash_t *hash, void *key);
hash_node_t* hash_get_node_by_key(hash_t *hash, void *key, unsigned int key_size);


hash_t *hash_alloc(unsigned int buckets, hashfunc_t hash_func)
{
	hash_t *hash = (hash_t *)malloc(sizeof(hash_t));
	//assert(hash != NULL);
	hash->buckets = buckets;
	hash->hash_func = hash_func;
	int size = buckets * sizeof(hash_node_t *);
	hash->nodes = (hash_node_t **)malloc(size);
	memset(hash->nodes, 0, size);
	return hash;
}

void* hash_lookup_entry(hash_t *hash, void* key, unsigned int key_size)
{
	hash_node_t *node = hash_get_node_by_key(hash, key, key_size);
	if (node == NULL) 
	{
		return NULL;
	}

	return node->value;
}

void hash_add_entry(hash_t *hash, void *key, unsigned int key_size,
	void *value, unsigned int value_size)
{
	if (hash_lookup_entry(hash, key, key_size))
	{
		fprintf(stderr, "duplicate hash key\n");
		return;
	}

	hash_node_t *node = malloc(sizeof(hash_node_t));
	node->prev = NULL;
	node->next = NULL;

	node->key = malloc(key_size);
	memcpy(node->key, key, key_size);

	node->value = malloc(value_size);
	memcpy(node->value, value, value_size);

	hash_node_t **bucket = hash_get_bucket(hash, key);
	if (*bucket == NULL) 
	{
		*bucket = node;
	} 
	else 
	{
		// 将新结点插入到链表头部
		node->next = *bucket;
		(*bucket)->prev = node;
		*bucket = node;
	}

}

void hash_free_entry(hash_t *hash, void *key, unsigned int key_size)
{
	hash_node_t *node = hash_get_node_by_key(hash, key, key_size);
	if (node == NULL) 
	{
		return;
	}

	free(node->key);
	free(node->value);

    if (node->prev) 
	{
		node->prev->next = node->next;
    } 
	else 
	{
		hash_node_t **bucket = hash_get_bucket(hash, key);
		*bucket = node->next;
	}

	if (node->next)
		node->next->prev = node->prev;

	free(node);

}

hash_node_t** hash_get_bucket(hash_t *hash, void *key)
{
	unsigned int bucket = hash->hash_func(hash->buckets, key);
	if (bucket >= hash->buckets)
	{
		fprintf(stderr, "bad bucket lookup\n");
		exit(EXIT_FAILURE);
	}

	return &(hash->nodes[bucket]);
}

hash_node_t* hash_get_node_by_key(hash_t *hash, void *key, unsigned int key_size)
{
	hash_node_t **bucket = hash_get_bucket(hash, key);
	hash_node_t *node = *bucket;
	if (node == NULL)
	{
		return NULL;
	}

	while (node != NULL && memcmp(node->key, key, key_size) != 0)
	{
		node = node->next;
	}

	return node;
}

定义两个hash表:

	s_ip_count_hash = hash_alloc(193, hash_func);
	s_pid_ip_hash   = hash_alloc(193, hash_func);

在session会话结构体中添加num_this_ip成员。在主线程序中,父进程登记pid–IP表。在主线程序中,来一个客户端:

unsigned int handle_ip_count(void *ip)
{
	unsigned int count;
	unsigned int *p_count = (unsigned int *)hash_lookup_entry(s_ip_count_hash, ip, sizeof(unsigned int));
	if (p_count == NULL)//查找出来的p_count为空说明是新的IP,将其count置为1,插入hash表
	{
		count = 1;
		hash_add_entry(s_ip_count_hash, ip, sizeof(unsigned int),&count, sizeof(unsigned int));
	}
	else//否则给对应的count++
	{
		count = *p_count;
		++count;
		*p_count = count;
	}
	return count;
}

那么在ftp进程退出的时候,如何维护呢?之前的进程模型,对子进程结束之后发出的信号设置忽略,防止产生僵尸进程。现在对该进程模型进行一定的修改:

signal(SIGCHLD, handle_sigchld);

主线进程收到子进程结束发来的SIGCHLD信号会执行handle_sigchld函数。

void handle_sigchld(int sig)
{
	pid_t pid;
	while((pid = waitpid(-1, NULL, WNOHANG)) > 0)//回收子进程
	{
		client_counts--;//总的最大连接数减一
		//通过pid查找IP
		unsigned int *ip = hash_lookup_entry(s_pid_ip_hash, &pid, sizeof(pid));
		if (ip == NULL)//???
		{
			continue;
		}
		//减少IP对应的count
		drop_ip_count(ip);
		//然后释放该pid--IP节点
		hash_free_entry(s_pid_ip_hash, &pid, sizeof(pid));
	}
}

void drop_ip_count(void *ip)
{
	unsigned int count;
	//通过IP查表得到对应count
	unsigned int *p_count = (unsigned int *)hash_lookup_entry(s_ip_count_hash, ip, sizeof(unsigned int));
	if (p_count == NULL)
	{
		return;
	}
	//count--
	count = *p_count;
	--count;
	*p_count = count;
	//如果count减少到0,则释放IP--count节点
	if (count == 0)
	{
		hash_free_entry(s_ip_count_hash, ip, sizeof(unsigned int));
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FTP服务器,又称为File Transfer Protocol Server,是网络上的一种文件传输协议,主要用于将文件从一个网络地址传输到另一个网络地址。其中,FTP Server指的是运行FTP协议的服务器,它负责接受来自客户端的请求,并按照FTP协议的规定进行响应。 FTP服务器有着广泛的应用,其中最常见的是Web服务器中的FTP服务器。FTP服务器可以提供文件上传和下载服务,主要用于网站的文件发布、备份和存储等。此外,FTP服务器还可以用于文件的共享、远程控制、安装程序等多种应用场景。 在工作中,我们可能需要使用一些迷你FTP服务器,以方便我们进行一些文件的传输和共享。所谓迷你FTP服务器,指的是一些小型的FTP服务器软件,它们具有简单易用的操作界面和快速高效的文件传输速度,适用于小型团队和个人使用。 与传统的FTP服务器相比,迷你FTP服务器不仅功能强大,而且占用资源较少,使得它们得以在性能不足的电脑上运行。此外,迷你FTP服务器还可以方便地进行设置和配置,以满足用户的个性化需求。 总的来说,迷你FTP服务器是一种实用的工具,它为用户提供了一种快速、安全、高效的文件传输和共享方式,值得我们在工作和生活中多加利用。 ### 回答2: FTP服务器也就是File Transfer Protocol服务器,是一种可以实现文件传输的服务器,可以提供文件上传、下载和管理等功能。FTP服务器分为大型和迷你类两种,其中迷你FTP服务器由于其轻量、易用、便携等特性,成为了广泛应用的一种FTP服务器。 迷你FTP服务器具有简单易用的特点,可以轻松搭建FTP服务器并实现文件的上传和下载。其操作简单,用户只需创建FTP用户账号,指定其访问目录,就可以实现上传下载管理等功能。同时,迷你FTP服务器的便携性也是其具有优秀特性之一,它可以在不同计算机上使用,只需将软件安装在u盘或移动硬盘中,便携性大大提高了其使用的便利性。 迷你FTP服务器还具有可扩展性和高度可定制性。FTP服务器可以通过插件等方式来扩展其功能,并可以通过调整参数和配置来实现自定义的功能和使用方式。这样,用户就可以根据自己的需求进行定制化,提高FTP服务器的作用和效率。 总而言之,迷你FTP服务器是一种轻量级FTP服务器,具有简单易用、便携性、可扩展性和高度可定制性等优点。对于需要上传、下载和管理文件的小型组织或个人用户而言,迷你FTP服务器是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值