код раньше работал. не знаю, может в ядре что-то поменялось. код работал дня три назад. а вчера перестал работать. 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 );
}
}