Exemplo n.º 1
0
/**
* Kill the server.  This function can be called from another thread to kill the
* server, causing runServer() to return.
*/
void killServer(void) {
	fprintf(stdout, "Stopping socket listener event loop.\n");
	if (event_base_loopexit(evbase_accept, NULL)) {
		perror("Error shutting down server");
	}
	fprintf(stdout, "Stopping workers.\n");
	workqueue_shutdown(&workqueue);
}
Exemplo n.º 2
0
/**
* Run the server.  This function blocks, only returning when the server has terminated.
*/
int runServer(void) {
	int sockfd;
	struct sockaddr_in listen_addr;
	struct event ev_accept;
	int reuseaddr_on;

	/* Initialize libevent. */
	event_init();

	/* Set signal handlers
	 sigset_t:信号集,其被定义为一种数据类型
	 struct sigaction {
	 void     (*sa_handler)(int);	//此参数和signal()的参数handler 相同, 代表新的信号处理函数
	 void     (*sa_sigaction)(int, siginfo_t *, void *);
	 sigset_t   sa_mask;			//用来设置在处理该信号时暂时将sa_mask 指定的信号搁置
	 int        sa_flags;			//用来设置信号处理的其他相关操作,  A_NOCLDSTOP: 如果参数signum 为SIGCHLD, 则当子进程暂停时并不会通知父进程;SA_RESTART: 被信号中断的系统调用会自行重启;
	 void     (*sa_restorer)(void);	//此参数没有使用
	 };
	*/
	sigset_t sigset;
	sigemptyset(&sigset);	//初始化信号集,信号集里面的所有信号被清空
	/*struct sigaction siginfo = {
		.sa_handler = sighandler,
		.sa_mask = sigset,
		.sa_flags = SA_RESTART,
		};*/
	struct sigaction siginfo;
	siginfo.sa_handler = sighandler;
	siginfo.sa_mask = sigset;
	siginfo.sa_flags = SA_RESTART;
	sigaction(SIGINT, &siginfo, NULL);	//程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出 
	sigaction(SIGTERM, &siginfo, NULL);	//程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理.通常用来要求程序自己正常退出.shell命令kill缺省产生这个信号.
	/* Create our listening socket. */
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0) {
		err(1, "listen failed");
	}
	memset(&listen_addr, 0, sizeof(listen_addr));
	listen_addr.sin_family = AF_INET;
	listen_addr.sin_addr.s_addr = INADDR_ANY;
	listen_addr.sin_port = htons(SERVER_PORT);
	if (bind(sockfd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
		err(1, "bind failed");
	}
	if (listen(sockfd, CONNECTION_BACKLOG) < 0) {
		err(1, "listen failed");
	}
	reuseaddr_on = 1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on));

	/* Set the socket to non-blocking, this is essential in event
	* based programming with libevent. */
	if (setnonblock(sockfd) < 0) {
		err(1, "failed to set server socket to non-blocking");
	}
	evbase_accept = event_base_new();
	if (NULL == evbase_accept)
	{
		perror("Unable to create socket accept event base");
		close(sockfd);
		return 1;
	}

	/* Initialize work queue. */
	if (workqueue_init(&workqueue, NUM_THREADS)) {
		perror("Failed to create work queue");
		close(sockfd);
		workqueue_shutdown(&workqueue);
		return 1;
	}

	/* We now have a listening socket, we create a read event to
	* be notified when a client connects. */
	event_set(&ev_accept, sockfd, EV_READ | EV_PERSIST, on_accept, (void *)&workqueue);
	event_base_set(evbase_accept, &ev_accept);
	event_add(&ev_accept, NULL);

	printf("Server is running...\n");

	/* Start the event loop. */
	event_base_dispatch(evbase_accept);

	event_base_free(evbase_accept);
	evbase_accept = NULL;

	close(sockfd);

	printf("Server shutdown.\n");

	return 0;
}
Exemplo n.º 3
0
/**
 * Run the server.  This function blocks, only returning when the server has terminated.
 */
int runServer(void) {
	int listenfd;
	struct sockaddr_in listen_addr;
	struct event ev_accept;
	int reuseaddr_on;

	/* Initialize libevent. */
	event_init();

	/* Set signal handlers */
	sigset_t sigset;
	sigemptyset(&sigset);
	struct sigaction siginfo = {
		.sa_handler = sighandler,
		.sa_mask = sigset,
		.sa_flags = SA_RESTART,
	};
	sigaction(SIGINT, &siginfo, NULL);
	sigaction(SIGTERM, &siginfo, NULL);

	/* Create our listening socket. */
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd < 0) {
		err(1, "listen failed");
	}
	memset(&listen_addr, 0, sizeof(listen_addr));
	listen_addr.sin_family = AF_INET;
	listen_addr.sin_addr.s_addr = INADDR_ANY;
	listen_addr.sin_port = htons(SERVER_PORT);
	if (bind(listenfd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
		err(1, "bind failed");
	}
	if (listen(listenfd, CONNECTION_BACKLOG) < 0) {
		err(1, "listen failed");
	}
	reuseaddr_on = 1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on));

	/* Set the socket to non-blocking, this is essential in event
	 * based programming with libevent. */
	if (setnonblock(listenfd) < 0) {
		err(1, "failed to set server socket to non-blocking");
	}

	if ((evbase_accept = event_base_new()) == NULL) {
		perror("Unable to create socket accept event base");
		close(listenfd);
		return 1;
	}

	/* Initialize work queue. */
	if (workqueue_init(&workqueue, NUM_THREADS)) {
		perror("Failed to create work queue");
		close(listenfd);
		workqueue_shutdown(&workqueue);
		return 1;
	}

	/* We now have a listening socket, we create a read event to
	 * be notified when a client connects. */
	event_set(&ev_accept, listenfd, EV_READ|EV_PERSIST, on_accept, (void *)&workqueue);
	event_base_set(evbase_accept, &ev_accept);
	event_add(&ev_accept, NULL);

	printf("Server running.\n");

	/* Start the event loop. */
	event_base_dispatch(evbase_accept);

	event_base_free(evbase_accept);
	evbase_accept = NULL;

	close(listenfd);

	printf("Server shutdown.\n");

	return 0;
}