@xverizex

Epoll возвращает событие с файловым дескриптором 0, хотя раньше работало, что может быть не так?

код раньше работал. не знаю, может в ядре что-то поменялось. код работал дня три назад. а вчера перестал работать. events возвращает нулевой файловый дескриптор, хотя такого не должно быть. вот код сервера. тут все написано.
/*
 * server.c - server for game.
 * author: Naidolinskii Dmitrii
 *******************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "db.h"
#include "config.h"
#include "events.h"

/* сокет сервера */
static int sockfd;
extern struct conf conf;
struct sockaddr_in in_server;
int epollfd, nfds;
#define AUTH_ADMIN            0
#define AUTH_GAMER            1
char sym[2] = { '!', '1' };

#define DEFAULT_SIZE_POLL        65535
#define DEFAULT_SIZE_DATA         1024

struct epoll_event ev, events[DEFAULT_SIZE_POLL];

static void *thread_control_clients ( void *data ) {

	while ( 1 ) {
		nfds = epoll_wait ( epollfd, events, DEFAULT_SIZE_POLL, -1 );
		printf ( "nfds: %d\n", nfds );
		if ( nfds == 0 ) continue;
		if ( nfds == -1 ) {
			perror ( "poll" );
			exit ( EXIT_FAILURE );
		}
		for ( int i = 0; i < nfds; i++ ) {
			char data[DEFAULT_SIZE_DATA + 1];
			printf ( "read ( %d )\n", events[i].data.fd );
			int ret = read ( events[i].data.fd, data, DEFAULT_SIZE_DATA );
			printf ( "ret: %d\n", ret );
			if ( ret <= 0 ) {
				char *byte = (char *) events[i].data.ptr;
				if ( byte ) {
					if ( *byte == sym[AUTH_GAMER] ) db_offline_user ( events[i].data.fd );
					if ( events[i].data.ptr ) free ( events[i].data.ptr );
				}
				epoll_ctl ( epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i] );
				/* здесь отправить другому игроку о том что игрок вышел из боя, если проводится бой. */
				continue;
			}
			switch ( data[0] ) {
				case '!':
					{
						int ret = db_register_admin ( &data[1] );
						switch ( ret ) {
							case EVENT_EVENT_FALSE:
								/* можно вывести сообщение об ошибке */
								write ( events[i].data.fd, "false", 6 );
								epoll_ctl ( epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i] );
								close ( events[i].data.fd );
								break;
							default:
								{
									events[i].data.ptr = &sym[AUTH_ADMIN];
									write ( events[i].data.fd, "!", 2 );
								}
								break;
						}
					}
					break;
				case '0':
					{
						int ret = db_registration ( &data[1], events[i].data.fd );
						switch ( ret ) {
							case EVENT_USER_IS_ONLINE:
								/* отправить сообщение что пользователь онлайн
								 * оборвать соединение */
								epoll_ctl ( epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i] );
								close ( events[i].data.fd );
								printf ( "пользователь уже есть в игре %d\n", events[i].data.fd );
								continue;
								break;
							case EVENT_EVENT_FALSE:
								/* неправильные данные */
								printf ( "неправильные данные.\n" );
								epoll_ctl ( epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i] );
								close ( events[i].data.fd );
								break;
							default:
								{
									events[i].data.ptr = &sym[AUTH_GAMER];
									write ( events[i].data.fd, "1", 2 );
								}
								break;
						}
					}
					break;
			}
		}
	}
}

/* создание потока */
void create_thread ( ) {
	epollfd = epoll_create1 ( 0 );
	if ( epollfd == -1 ) {
		perror ( "epoll_create" );
		exit ( EXIT_FAILURE );
	}

	pthread_t t;
	pthread_create ( &t, NULL, thread_control_clients, NULL );
}

void wait_client ( ) {
	socklen_t soss = sizeof ( in_server );
	int client = accept ( sockfd, ( struct sockaddr * ) &in_server, &soss );
	if ( client == -1 ) return;
	printf ( "%d подключен.\n", client );
#if 0
	int ret = fcntl ( client, F_SETFD, ( fcntl ( client, F_GETFD ) | O_NONBLOCK ) );
	if ( ret == -1 ) {
		perror ( "fcntl" );
	}
#endif
	ev.events = EPOLLIN;
	ev.data.fd = client;
	ev.data.ptr = NULL;
	if ( epoll_ctl ( epollfd, EPOLL_CTL_ADD, client, &ev ) == -1 ) {
		perror ( "epoll_ctl" );
		exit ( EXIT_FAILURE );
	}
}

/* конфигурация сокета */
void configure_socket ( ) {
	 sockfd = socket ( AF_INET, SOCK_STREAM, 0 );
	 if ( sockfd == -1 ) {
		 perror ( "socket" );
		 exit ( EXIT_FAILURE );
	 } 

	 int ret;
	 {
		int opt = 1;
	 	ret = setsockopt ( sockfd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof ( opt ) );
		if ( ret == -1 ) {
			perror ( "sock opt SO_REUSEPORT" );
			exit ( EXIT_FAILURE );
		}
	 }

	 in_server.sin_family = AF_INET;
	 in_server.sin_port = htons ( conf.port );
	 inet_aton ( "127.0.0.1", &in_server.sin_addr );
	// in_server.sin_addr.s_addr = 0;
	 ret = bind ( sockfd, ( struct sockaddr *) &in_server, sizeof ( in_server ) );
	 if ( ret == -1 ) {
		 perror ( "bind" );
		 exit ( EXIT_FAILURE );
	 }
	 ret = listen ( sockfd, conf.listen );
	 if ( ret == -1 ) {
		 perror ( "listen" );
		 exit ( EXIT_FAILURE );
	 }

}
  • Вопрос задан
  • 40 просмотров
Пригласить эксперта
Ответы на вопрос 1
@xverizex Автор вопроса
А, всё, понял в чём проблема. оказывается в events fd и ptr это union, и поэтому когда я указывал ptr = NULL, то занулял fd. теперь ясно. блин, а я на основе ptr делал код, думал что это дополнительное удобство. Ну ладно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы