⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 本Linux网络应用程序采用客户-服务器模型,并发型交互。在OSI参考模型的传输层,通过调用TCP套接字(Socket)的各种函数,使服务器和各个客户端之间建立快速可靠的连接
💻 C
📖 第 1 页 / 共 2 页
字号:
	}/*end of while(1)*/

	do_exit();
}/*end of main procedure*/

void do_exit()
{
	int id = pthread_self();

	if (id == timerid)
		return;

	pthread_cancel(timerid);

	free_flowlist();

	exit(0);
}


int init_config()
{
	FILE *fp = NULL;
	char linebuf[BUF_LEN];
	struct flow_info *flow = NULL;
	int wordnum;
	char **wordlist = NULL;
	int ret = -1;


	if ((fp = fopen(CONFIG_FILE, "r")) == NULL) {
		DEBUG("open file %s error", CONFIG_FILE);
		goto done;
	}

	memset(linebuf, 0, sizeof(linebuf));
	while (fgets(linebuf, sizeof(linebuf), fp) != NULL) {
		if (linebuf[0] == '#')
			continue;

		STRIP(linebuf, '\n');

		DEBUG("get line[%s]", linebuf);

		wordnum = parse_line(linebuf, ",", &wordlist, 1);
		if (wordnum <= 0) {
			DEBUG("null line or error line");
			continue;
		}

		if (wordnum != 6) {
			DEBUG("format error[%d]", wordnum);
			goto done;
		}

		flow = (struct flow_info *)malloc(sizeof(struct flow_info));
		if (flow == NULL) {
			DEBUG("malloc eror");
			goto done;
		}

		memset(flow, 0, sizeof(*flow));		flow->ID = atoi(wordlist[0]);
		flow->sip = ip2val(wordlist[1]);
		flow->dip = ip2val(wordlist[2]);
		flow->type = atoi(wordlist[3]);
		flow->value = str2ll(wordlist[4], DEC);
		flow->feeRatio=atoi(wordlist[5]);		
		flow->next = flow_list;
		flow_list = flow;

		if (wordlist && wordnum > 0) {
			memset(wordlist, 0, wordnum * sizeof(char*));
			free(wordlist);
			wordlist = NULL;
		}

	}

	ret = 0;

done:
	FCLOSE(fp);

	if (wordlist && wordnum > 0) {
		memset(wordlist, 0, wordnum * sizeof(char*));
		free(wordlist);
	}

	dump_flowlist();
	return ret;

}

void free_flowlist()
{
	struct flow_info *flow = NULL;

	while (flow_list) {
		flow = flow_list;
		flow_list = flow->next;
		free(flow);
	}
}

void dump_flowlist()
{
	struct flow_info *flow = flow_list;
	char sip[16], dip[16];

	DEBUG("flow list:");
	while (flow) {
		DEBUG("sip:%s dip:%s type:%d value:%llu", 
			val2ip(flow->sip, sip), val2ip(flow->dip, dip), 
			flow->type, flow->value);
		flow = flow->next;
	}
}

//流量检测函数。
//参数IP表示客户端的IP地址,SIZE表示此次产生的流量数。
//返回值:	0:表示可以使用。
//    		1:表示超过流量,不能使用
//		2:表示没有规则,默认不使用。
//		3:表示达到最大同时连接数,禁止使用。
int check_flowlist(unsigned int ip, int size)

{
	struct avl_node *node = NULL;
	struct avl_data *data = NULL;
	struct flow_info *info = NULL;
	char ipbuf[16];

	DEBUG("check flow list with ip[%s] size[%d]", val2ip(ip, ipbuf), size);

	if ((node = avl_find(&avltree, (unsigned char *)&ip)) != NULL) { //在已有的连接中找此用户
		//如果此用户已经有连接
		data = NODE_RESOLVE(node);
		DEBUG("node found in avltree");
		DEBUG("ip:%s type:%d value:%llu used:%llu time:%s", 
			val2ip(data->ip, ipbuf), data->type, data->value, data->used, ctime(&(data->time)));

		if (data->type == 0) //?类型为0,返回0。(可能为特殊权限用户(不限流量))
			return 0;

		if (data->used + size > data->value) //已用加上此次产生的流量大于限制流量,禁止使用。
			return 1;
		else
		{
			data->used += size;  //记录此次的流量,
			recordFee(data->ID,data->feeRatio,size);//记录费用
		}
	} else {
		DEBUG("New Account\n");
		if ((info = find_flowlist(ip)) == NULL) //未找到此用用户,禁止使用。
			return 2;

		if (info->type == 0) //特殊用户,不限制。
			return 0;

		if (info->value < size) //此次使用量大于限制量,禁止使用。
			return 1;

		if (flow_list == NULL) //超过最大连接数。
			return 3;
		
		pthread_mutex_lock(&lockavl); 

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

		if (used_node)
			used_node->prev = node;
		node->next = used_node;
		node->prev = NULL;
		used_node = node;
		//记录当前用户信息。
		data = NODE_RESOLVE(node);
		data->ip = ip;		
		data->type = info->type;
		data->value = info->value;
		data->used = size;	data->ID=info->ID;
data->feeRatio=info->feeRatio;	

		time(&data->time);

		DEBUG("create new node");
		DEBUG("ip:%s type:%d value:%llu used:%llu time:%s", 
			val2ip(data->ip, ipbuf), data->type, data->value, data->used, ctime(&(data->time)));
		recordFee(data->ID,data->feeRatio,size);//记录费用

		avl_insert(&avltree, node);

		pthread_mutex_unlock(&lockavl);	}

	return 0;

}

struct flow_info *find_flowlist(unsigned int ip)
{
	struct flow_info *info = flow_list;

	while (info) {
		if (ip >= info->sip && ip <= info->dip) //IP在一个范围之内,
			break;

		info = info->next;
	}

	return info;
}

void dump_usedlist()
{
	struct avl_node *node = used_node;
	struct avl_data *data = NULL;
	char ip[16];
	int num = 0;

	DEBUG("used list:");
	while (node) {
		data = NODE_RESOLVE(node);
		num++;
		DEBUG("%d ip:%s type:%d value:%llu used:%llu time:%s", 
			num, val2ip(data->ip, ip), data->type, data->value, data->used, ctime(&data->time));
		node = node->next;
	}

}

void *server_timer(void *arg)
{
	struct avl_node *node = NULL;
	struct avl_data *data = NULL;
	time_t curr;
	struct tm *m1 = NULL, *m2 = NULL;
	int t;

	pthread_detach(pthread_self());

	DEBUG("server_timer pid : %u", getpid());
	DEBUG("server_timer thread id : %d", (int)pthread_self());

	while (1) {
		//DEBUG("come in server_timer ...");

		pthread_mutex_lock(&lockavl);

		curr = time(NULL);

		node = used_node;
		while (node) {
			data = NODE_RESOLVE(node);

			m1 = localtime(&data->time);
			m2 = localtime(&curr);
			switch (data->type) {
				case 1:	/* every hour */
					t = m2->tm_hour - m1->tm_hour;
					break;
				case 2:	/* every day */
					t = m2->tm_mday - m1->tm_mday;
					break;
				case 3:	/* every month */
					t = m2->tm_mon - m1->tm_mon;
					break;
				default:
					t = 1;
					break;
			}

			if (t > 0) {
		        if (node->prev) 
					node->prev->next = node->next;
				else
					used_node = node->next;

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

				node->next = NULL;
				node->prev = NULL;

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

			}

		}

		pthread_mutex_unlock(&lockavl);

		sleep(SERVER_TIMER_INTER);
	}

}

void daemon_init()
{
	int i, maxfd;

	if (fork() != 0)
		exit(1);

	if (setsid() < 0)
        exit(1);

	if (fork() != 0)
		exit(1);

//	chdir("/");
	umask(0);

	maxfd = sysconf(_SC_OPEN_MAX);
	for (i = 0; i < maxfd; i++)
		close(i);

	open("/dev/null", O_RDWR);
	dup(0);
	dup(1);
	dup(2);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -