Answer the question
In order to leave comments, you need to log in
Epoll returns an event with file descriptor 0, although it worked before, what could be wrong?
the code used to work. I do not know, maybe something has changed in the kernel. The code worked three days ago. but yesterday it stopped working. events returns a null file descriptor, although it shouldn't. here is the server code. everything is written here.
/*
* 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 );
}
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question