как сделать poll или select сервер для приема клиентов?

не могу понять как сделать сервер, в котором можно добавить нового клиента в select или poll и получать события. При том ещё и не потерять данные, если в select или poll будет установлен таймер ( или для сокета сетевые данные буферизируются, пока не закроется сокет? ). вот какой сделал код.

/*
 * 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/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <poll.h>
#include "config.h"

/* сокет сервера */
static int sockfd;
extern struct conf conf;
struct sockaddr_in in_server;

#define DEFAULT_SIZE_POLL        65535
#define DEFAULT_SIZE_DATA         1024

struct pollfd fds[DEFAULT_SIZE_POLL];
int index_poll;

static void *thread_control_clients ( void *data ) {

    while ( 1 ) {
        int client = poll ( fds, DEFAULT_SIZE_POLL, -1 );
        if ( client == -1 ) {
            perror ( "poll" );
            exit ( EXIT_FAILURE );
        }
        if ( client ) {
            char data[DEFAULT_SIZE_DATA + 1];
            read ( client, data, DEFAULT_SIZE_DATA );
            printf ( "%d: %s\n", client, data );
        }
    }
}

/* создание потока */
void create_thread ( ) {
    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 );


}

/* конфигурация сокета */
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 );
     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 );
     }

     for ( int i = 0; i < DEFAULT_SIZE_POLL; i++ ) {

        fds[i].fd = s;
        fds[i].events = POLLIN | POLLOUT;

     }
}

Ответы (2 шт):

Автор решения: Sergey

Тот код, что Вы привели, он выглядит довольно....оригинально. На самом деле, существуют определённые (почти) стандарты, для разработки сетевых приложений. Настоятельно рекомендую посмотреть книжку

UNIX: разработка сетевых приложений. 3-е изд.
Стивенс У. Р., Феннер Б., Рудофф Э. M. 

https://avidreaders.ru/book/unix-razrabotka-setevyh-prilozheniy-3-e.html

Там всё описано в деталях.

→ Ссылка
Автор решения: xverizex

Решение с epoll.

/*
 * 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 "config.h"

/* сокет сервера */
static int sockfd;
extern struct conf conf;
struct sockaddr_in in_server;
int epollfd, nfds;

#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];
            int ret = read ( events[i].data.fd, data, DEFAULT_SIZE_DATA );
            if ( ret == -1 || ret == 0 ) {
                epoll_ctl ( epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i] );
                continue;
            }
            char *s = strchr ( data, '\n' );
            if ( s ) *s = 0;
            s = strchr ( data, '\r' );
            if ( s ) *s = 0;
            data[ret] = 0;
            printf ( "%d: %s\n", events[i].data.fd, data );
        }
    }
}

/* создание потока */
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 );
    ev.events = EPOLLIN;
    ev.data.fd = client;
    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 );
     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 );
     }

}
→ Ссылка