LinuxはSelectで高同時サーバーを構築


//サービス側

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
 
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8000
 
 
#define MAX_RECV_LEN 1024
#define MAX_CLIENT_NUM 30
#define BACK_LOG 20
 
 
static int running = 1;
 
 
int main(int argc, char *argv[])
{
	int sock_fd = -1;
	int ret = -1;
	struct sockaddr_in serv_addr;
	struct sockaddr_in cli_addr;
	socklen_t serv_addr_len = 0;
	socklen_t cli_addr_len = 0;
	int client_fd[MAX_CLIENT_NUM];
	char recv_buf[MAX_RECV_LEN];
	int new_conn_fd = -1;
	int i = 0;
	int max_fd = -1;
	int num = -1;
	struct timeval timeout;
 
 
	fd_set read_set;
	fd_set write_set;
	fd_set select_read_set;
 
 
	FD_ZERO(&read_set);
	FD_ZERO(&write_set);
	FD_ZERO(&select_read_set);
 
	for (i = 0; i < MAX_CLIENT_NUM; i++)
	{
		client_fd[i] = -1;
	} 
 
	memset(&serv_addr, 0, sizeof(serv_addr));
	memset(&cli_addr, 0, sizeof(cli_addr));
 
 
	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_fd < 0)
	{
		perror("Fail to socket");
		exit(1);
	}
 
 
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT);
	serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
 
 
	unsigned int value = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
				(void *)&value, sizeof(value)) < 0)
	{
		perror("Fail to setsockopt");
		exit(1);
	}
 
 
	serv_addr_len = sizeof(serv_addr);
	if (bind(sock_fd, (struct sockaddr*)&serv_addr, serv_addr_len) < 0)
	{
		perror("Fail to bind");
		exit(1);
	}
	if (listen(sock_fd, BACK_LOG) < 0)
	{
		perror("Fail to listen");
		exit(1);
	}
 
	char buf[1024];
	max_fd = sock_fd;
	int len;
	FD_SET(sock_fd, &read_set);
	while (running)
	{
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;
 
 
		max_fd = sock_fd;
		for (i = 0; i < MAX_CLIENT_NUM; i++)
		{
			if (max_fd < client_fd[i])
			{
				max_fd = client_fd[i];
			}
		}
 
 
		select_read_set = read_set;
		ret = select(max_fd + 1, &select_read_set, NULL, NULL, &timeout);
		if (ret == 0)
		{
			printf("timeout
"
); } else if (ret < 0) { printf("error occur
"
); } else { if (FD_ISSET(sock_fd, &select_read_set)) { printf("new client comes
"
); len = sizeof(cli_addr); new_conn_fd = accept(sock_fd, (struct sockaddr*)&cli_addr, &len); if (new_conn_fd < 0) { perror("Fail to accept"); exit(1); } else { for (i = 0; i < MAX_CLIENT_NUM; i++) { if (client_fd[i] == -1) { client_fd[i] = new_conn_fd; FD_SET(new_conn_fd, &read_set); break; } if (max_fd < new_conn_fd) { max_fd = new_conn_fd; } } } } else { for (i = 0; i < MAX_CLIENT_NUM; i++) { if (-1 == client_fd[i]) { continue; } memset(recv_buf, 0, MAX_RECV_LEN); if (FD_ISSET(client_fd[i], &select_read_set)) { num = read(client_fd[i], recv_buf, MAX_RECV_LEN); if (num < 0) { printf("Client(%d) left
"
, client_fd[i]); FD_CLR(client_fd[i], &read_set); close(client_fd[i]); client_fd[i] = -1; } else if (num > 0) { recv_buf[num] = '\0'; printf("Recieve client(%d) data
"
, client_fd[i]); printf("Data: %s

"
, recv_buf); } if (num == 0) { printf("Client(%d) exit
"
, client_fd[i]); FD_CLR(client_fd[i], &read_set); close(client_fd[i]); client_fd[i] = -1; } } } } } } return 0; }

//クライアント
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
 
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8000
 
 
#define MAX_RECV_LEN 1024
 
 
static int running = 1;
 
 
int main(int argc, char *argv[])
{
	int sock_fd = -1;
	int ret = -1;
	struct sockaddr_in serv_addr;
	struct sockaddr_in cli_addr;
	socklen_t serv_addr_len = 0;
 
	memset(&serv_addr, 0, sizeof(serv_addr));
 
 
	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_fd < 0)
	{
		perror("Fail to socket");
		exit(1);
	}
 
 
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT);
	serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
 
 
	serv_addr_len = sizeof(serv_addr);
	if (connect(sock_fd, (struct sockaddr *)&serv_addr, serv_addr_len) < 0)
	{
		perror("Fail to connect");
		exit(1);
	}
	char buf[1024];
	int num = 0;
	while (running)
	{
		num = read(STDIN_FILENO, buf, MAX_RECV_LEN);
		if (num > 0)
		{
			buf[num] = '\0';
			printf("buf: %s
"
, buf); num = write(sock_fd, buf, num); if (num < 0) { printf("write failed
"
); exit(1); } if (strncmp(buf, "exit", strlen("exit")) == 0) { printf("Client exit
"
); close(sock_fd); return 0; } } } return 0; }