示例#1
0
/* 客户端退出处理 */
void handle_recover(int sig)
{
	int i;
	if (sig == SIGCHLD)
	{
		pid_t pid = wait(0);
		printf("退出的子进程 pid = [%d]\n\n", pid);

		char tempIP[20]="",tempPid[10]="";
		sprintf(tempPid, "%d", pid);
		// 通过进程pid获取ip
		strcpy(tempIP, (char *)hash_getval(hash_pid_ip, tempPid, H_GET_VAL));
		if(tempIP != NULL)
		{
			printf("开始重新统计链接数:\n");
			printf("退出客户端IP=%s\n", tempIP);
			//得到指定IP的已连接数
			i = atoi((char *)hash_getval(hash_ip_count, tempIP, H_GET_VAL));
			if ( i > 1 )
			{
				// 连接数至少是2 则减1
				hash_del(hash_ip_count, tempIP, H_DEL_MINUS);//删除 1代表数量大于1
			}else
			{
				// 链接数为1 删除节点
				hash_del(hash_ip_count, tempIP, H_DEL_DESTROY);
			}
			printf("哈希表 IP连接数 【删除】 %s\n", tempIP);
			hash_del(hash_pid_ip, tempPid, H_DEL_DESTROY);
			printf("哈希表 进程IP联系 【删除】 %s\n", tempPid);
		}else
		{
			printf("哈希表 连接数统计失败!\n");
		}

		printf("\n当前客户端列表\n");
		for(i=0;i<HASH_MAX;i++)
		{
			if(hash_ip_count[i]!=NULL)
			{
				printf("客户端ip=%-15s  连接数=%-20s\n",hash_ip_count[i]->key,hash_ip_count[i]->val);
			}
		}
		printf("总计 %d 个链接\n", get_hash_length(hash_pid_ip) );
	}
}
示例#2
0
char *tdb1_summary(struct tdb_context *tdb)
{
	tdb1_off_t off, rec_off;
	struct tally freet, keys, data, dead, extra, hash, uncoal;
	struct tdb1_record rec;
	char *ret = NULL;
	bool locked;
	size_t len, unc = 0;
	struct tdb1_record recovery;

	/* We may have a write lock already, so don't lock. */
	if (tdb->file->allrecord_lock.count != 0) {
		locked = false;
	} else {
		if (tdb_lockall_read(tdb) != TDB_SUCCESS)
			return NULL;
		locked = true;
	}

	if (tdb1_recovery_area(tdb, tdb->tdb1.io, &rec_off, &recovery) != 0) {
		goto unlock;
	}

	tally1_init(&freet);
	tally1_init(&keys);
	tally1_init(&data);
	tally1_init(&dead);
	tally1_init(&extra);
	tally1_init(&hash);
	tally1_init(&uncoal);

	for (off = TDB1_DATA_START(tdb->tdb1.header.hash_size);
	     off < tdb->file->map_size - 1;
	     off += sizeof(rec) + rec.rec_len) {
		if (tdb->tdb1.io->tdb1_read(tdb, off, &rec, sizeof(rec),
					   TDB1_DOCONV()) == -1)
			goto unlock;
		switch (rec.magic) {
		case TDB1_MAGIC:
			tally1_add(&keys, rec.key_len);
			tally1_add(&data, rec.data_len);
			tally1_add(&extra, rec.rec_len - (rec.key_len
							 + rec.data_len));
			if (unc > 1)
				tally1_add(&uncoal, unc - 1);
			unc = 0;
			break;
		case TDB1_FREE_MAGIC:
			tally1_add(&freet, rec.rec_len);
			unc++;
			break;
		/* If we crash after ftruncate, we can get zeroes or fill. */
		case TDB1_RECOVERY_INVALID_MAGIC:
		case 0x42424242:
			unc++;
			/* If it's a valid recovery, we can trust rec_len. */
			if (off != rec_off) {
				rec.rec_len = tdb1_dead_space(tdb, off)
					- sizeof(rec);
			}
			/* Fall through */
		case TDB1_DEAD_MAGIC:
			tally1_add(&dead, rec.rec_len);
			break;
		default:
			tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
						TDB_LOG_ERROR,
						"Unexpected record magic 0x%x"
						" at offset %d",
						rec.magic, off);
			goto unlock;
		}
	}
	if (unc > 1)
		tally1_add(&uncoal, unc - 1);

	for (off = 0; off < tdb->tdb1.header.hash_size; off++)
		tally1_add(&hash, get_hash_length(tdb, off));

	/* 20 is max length of a %zu. */
	len = strlen(SUMMARY_FORMAT1) + 35*20 + 1;
	ret = (char *)malloc(len);
	if (!ret)
		goto unlock;

	snprintf(ret, len, SUMMARY_FORMAT1,
		 (tdb1_len_t)tdb->file->map_size, keys.total+data.total,
		 keys.num,
		 keys.min, tally1_mean(&keys), keys.max,
		 data.min, tally1_mean(&data), data.max,
		 extra.min, tally1_mean(&extra), extra.max,
		 dead.num,
		 dead.min, tally1_mean(&dead), dead.max,
		 freet.num,
		 freet.min, tally1_mean(&freet), freet.max,
		 hash.num,
		 hash.min, tally1_mean(&hash), hash.max,
		 uncoal.total,
		 uncoal.min, tally1_mean(&uncoal), uncoal.max,
		 keys.total * 100.0 / tdb->file->map_size,
		 data.total * 100.0 / tdb->file->map_size,
		 extra.total * 100.0 / tdb->file->map_size,
		 freet.total * 100.0 / tdb->file->map_size,
		 dead.total * 100.0 / tdb->file->map_size,
		 (keys.num + freet.num + dead.num)
		 * (sizeof(struct tdb1_record) + sizeof(uint32_t))
		 * 100.0 / tdb->file->map_size,
		 tdb->tdb1.header.hash_size * sizeof(tdb1_off_t)
		 * 100.0 / (tdb1_len_t)tdb->file->map_size);

unlock:
	if (locked) {
		tdb_unlockall_read(tdb);
	}
	return ret;
}
示例#3
0
_PUBLIC_ char *tdb_summary(struct tdb_context *tdb)
{
	off_t file_size;
	tdb_off_t off, rec_off;
	struct tally freet, keys, data, dead, extra, hashval, uncoal;
	struct tdb_record rec;
	char *ret = NULL;
	bool locked;
	size_t unc = 0;
	int len;
	struct tdb_record recovery;

	/* Read-only databases use no locking at all: it's best-effort.
	 * We may have a write lock already, so skip that case too. */
	if (tdb->read_only || tdb->allrecord_lock.count != 0) {
		locked = false;
	} else {
		if (tdb_lockall_read(tdb) == -1)
			return NULL;
		locked = true;
	}

	if (tdb_recovery_area(tdb, tdb->methods, &rec_off, &recovery) != 0) {
		goto unlock;
	}

	tally_init(&freet);
	tally_init(&keys);
	tally_init(&data);
	tally_init(&dead);
	tally_init(&extra);
	tally_init(&hashval);
	tally_init(&uncoal);

	for (off = TDB_DATA_START(tdb->hash_size);
	     off < tdb->map_size - 1;
	     off += sizeof(rec) + rec.rec_len) {
		if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec),
					   DOCONV()) == -1)
			goto unlock;
		switch (rec.magic) {
		case TDB_MAGIC:
			tally_add(&keys, rec.key_len);
			tally_add(&data, rec.data_len);
			tally_add(&extra, rec.rec_len - (rec.key_len
							 + rec.data_len));
			if (unc > 1)
				tally_add(&uncoal, unc - 1);
			unc = 0;
			break;
		case TDB_FREE_MAGIC:
			tally_add(&freet, rec.rec_len);
			unc++;
			break;
		/* If we crash after ftruncate, we can get zeroes or fill. */
		case TDB_RECOVERY_INVALID_MAGIC:
		case 0x42424242:
			unc++;
			/* If it's a valid recovery, we can trust rec_len. */
			if (off != rec_off) {
				rec.rec_len = tdb_dead_space(tdb, off)
					- sizeof(rec);
			}
			/* Fall through */
		case TDB_DEAD_MAGIC:
			tally_add(&dead, rec.rec_len);
			break;
		default:
			TDB_LOG((tdb, TDB_DEBUG_ERROR,
				 "Unexpected record magic 0x%x at offset %u\n",
				 rec.magic, off));
			goto unlock;
		}
	}
	if (unc > 1)
		tally_add(&uncoal, unc - 1);

	for (off = 0; off < tdb->hash_size; off++)
		tally_add(&hashval, get_hash_length(tdb, off));

	file_size = tdb->hdr_ofs + tdb->map_size;

	len = asprintf(&ret, SUMMARY_FORMAT,
		 (unsigned long long)file_size, keys.total+data.total,
		 (size_t)tdb->hdr_ofs, (size_t)tdb->map_size,
		 keys.num,
		 (tdb->hash_fn == tdb_jenkins_hash)?"yes":"no",
		 (unsigned)tdb->feature_flags, TDB_SUPPORTED_FEATURE_FLAGS,
		 (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX)?"yes":"no",
		 keys.min, tally_mean(&keys), keys.max,
		 data.min, tally_mean(&data), data.max,
		 extra.min, tally_mean(&extra), extra.max,
		 dead.num,
		 dead.min, tally_mean(&dead), dead.max,
		 freet.num,
		 freet.min, tally_mean(&freet), freet.max,
		 hashval.num,
		 hashval.min, tally_mean(&hashval), hashval.max,
		 uncoal.total,
		 uncoal.min, tally_mean(&uncoal), uncoal.max,
		 keys.total * 100.0 / file_size,
		 data.total * 100.0 / file_size,
		 extra.total * 100.0 / file_size,
		 freet.total * 100.0 / file_size,
		 dead.total * 100.0 / file_size,
		 (keys.num + freet.num + dead.num)
		 * (sizeof(struct tdb_record) + sizeof(uint32_t))
		 * 100.0 / file_size,
		 tdb->hash_size * sizeof(tdb_off_t)
		 * 100.0 / file_size);
	if (len == -1) {
		goto unlock;
	}

unlock:
	if (locked) {
		tdb_unlockall_read(tdb);
	}
	return ret;
}
示例#4
0
/* ftp运行函数 */
int start()
{
	//1.socket
	int listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if(listenfd==-1) ERR_EXIT("socket");

	//2.设置监听 ip/port
	struct sockaddr_in servaddr;
	memset(&servaddr, 0,sizeof(servaddr));

	servaddr.sin_family = PF_INET;//AF_INET
	servaddr.sin_port = htons(PORT_LISTEN);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	socklen_t seraddrlen =sizeof(servaddr);

	//设置地址重用
	int rel = serAddrReuse(listenfd);
	if (rel == -1) ERR_EXIT("setsockopt");

	int res = bind(listenfd, (struct sockaddr*)&servaddr, seraddrlen);
	if(res==-1) ERR_EXIT("bind");

	//3.listen侦听客户端的连接
	res=listen(listenfd, 5);
	if(res==-1) ERR_EXIT("listen");

	printf("-------------------------------------\n");
	printf("|       服务器端配置文件读取成功\n");
	printf("-------------------------------------\n");
	printf("|   服务器端ip	  =[%s]\n", LOCAL_IP);
	printf("|   监听端口port  =[%d]\n", PORT_LISTEN);
	printf("|   最大连接数	  =[%d]\n", MAX_COUNT);
	printf("|   同ip最大连接数=[%d]\n", MAX_IP_COUNT);
	printf("|   限制下载速度  =[%dkb/s]\n", LIMIT_SPEED*10);
	printf("-------------------------------------\n");

	//4.accept:接受客户端的连接,如果没有客户端连接进来, accept会阻塞,如果客户端连接进来了,accept会返回一个新的套接口,这个新的套接口就是与客户端进行数据通信的通道, 客户端的网络地址会填充进accept的第二个参数,第三个参数会是客户端地址的长度
	pid_t pid;
	MAIN_PID = getpid();

	// 安装进程回收信号
	signal(SIGCHLD, handle_recover);

	while(1)
	{
		// 阻塞,等待接收
		struct sockaddr_in cliaddr;
		memset(&cliaddr, 0,sizeof(cliaddr));
		socklen_t cliaddrlen =sizeof(cliaddr);
		connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen);
		if(connfd==-1) ERR_EXIT("accept");

		char now_ip[20] = "";
		strcpy(now_ip, inet_ntoa(cliaddr.sin_addr));

		printf("\n建立新连接!\n");
		printf("ip=%s\n", now_ip);
		printf("port=%d\n\n", ntohs(cliaddr.sin_port));

		// 发送welcome至客户端 getpeername(connfd, )
		write_loop(connfd, "220 welcome\r\n", strlen("220 welcome\r\n"));

		int conn_count=0, len=0;
		// 判断连接数控制
		if ( (conn_count = getIpConn(now_ip)) >= MAX_IP_COUNT )
		{
			printf("超过同ip连接数,当前为 %d 最大为 %d\n", conn_count, MAX_IP_COUNT);
			// 提示超过连接数
			write_loop(connfd, "421 Connection refused: too many sessions for this address.\r\n", strlen("421 Connection refused: too many sessions for this address.\r\n"));
			continue;
		}else if ( (len = get_hash_length(hash_pid_ip)) >= MAX_COUNT )
		{
			printf("超过总连接数,当前 %d 个链接\n",  len);
			write_loop(connfd, "421 Connection refused: too many sessions\r\n", strlen("421 Connection refused: too many sessions\r\n"));
		}

		printf("---------------------------------\n");
		printf("| 链接检测                     |\n");
		printf("|       目前同ip连接数 %2d      |\n", conn_count);
		printf("|       总计 %2d 个链接         |\n", len);
		printf("---------------------------------\n");

		pid = fork();
		switch(pid)
		{
		case -1:
			exit(-1);
		case 0://子进程
			close(listenfd);
			client_session();
			exit(EXIT_SUCCESS);
			break;
		default:
			close(connfd);
			printf("\n新客户端接入: pid=[%d] id=[%s]\n", pid, now_ip);

			char str_pid[10]="";
			itoa(str_pid, pid);
			hash_insert(hash_pid_ip, str_pid, now_ip, H_PID_IP, NULL);
			hash_insert(hash_ip_count, now_ip, NULL, H_IP_COUNT, NULL);

			int i;
			printf("-------------------------------------------------------\n");
			for(i=0;i<HASH_MAX;i++)
			{
				if(hash_ip_count[i]!=NULL)
				{
			printf("|       客户端ip=%-20s 连接数=%-30s  |\n",hash_ip_count[i]->key,hash_ip_count[i]->val);
				}
			}
			printf("|       总计 %2d 个链接                                \n", get_hash_length(hash_pid_ip));
			printf("-------------------------------------------------------\n");

			break;
		}
	}
}