// Classe Server #ifndef SERVER_HH_ # define SERVER_HH_ #include #include #include #include #include #include #include #include #include #include #include "data/Data.hh" extern char gl_handle; extern void signal_alarm(int); template class Data; class Server { public: Server(const int& port, const unsigned int& nb_client_max) { _port = port; _client_max = nb_client_max; _fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); _sock_in = new struct sockaddr_in; _sock_in->sin_family = PF_INET; _sock_in->sin_port = htons(port); _sock_in->sin_addr.s_addr = INADDR_ANY; if ((bind(_fd, (struct sockaddr *)_sock_in, sizeof (*_sock_in)) == -1) || (listen(_fd, 5) == -1)) this->error(); std::cout << "Server started. Listening on port " << _port << std::endl; _fd_client = new std::list; this->start_signal(); this->start(); } void start() { int fd_client; socklen_t len; struct sockaddr_in sock_client; len = sizeof (struct sockaddr_in); while (gl_handle != -1 && this->_fd_client->size() < _client_max) { fd_client = 0; if ((fd_client = accept(this->_fd, (struct sockaddr *)&(sock_client), &len)) > 0) gl_handle = gl_handle | 2; std::list list_fd; if (2 == (gl_handle & 2)) { this->accept_client(fd_client); this->send_signal(fd_client); std::cout << "Number of connected clients :" << this->_fd_client->size() << std::endl; } gl_handle = 0; this->test_client(); } } void test_client() { if (_fd_client->size()) { std::list::const_iterator fd_client_tmp; std::list::const_iterator fd_client = _fd_client->begin(); int i = 0; while (fd_client != _fd_client->end()) { i++; char c = 0; errno = 0; fd_client_tmp = fd_client; read(*fd_client, &c, sizeof(char)); ++fd_client; if (errno == 0) this->remove_client(*fd_client_tmp); } } } void error() { std::cerr << "Error server : "; perror(""); exit(errno); } void remove_client(const int& fd) { _fd_client->remove(fd); std::cout << "Client in the file descriptor : " << fd << " are disconnected" << std::endl; std::cout << "Number of connected clients :" << this->_fd_client->size() << std::endl; } void wait_signal(std::list& list_fd) // retourne la liste des files descriptors a lire { struct pollfd poll_fd[_fd_client->size()]; std::list::const_iterator fd = _fd_client->begin(); for (int i = 0; fd != _fd_client->end(); ++fd, ++i) { poll_fd[i].fd = *fd; poll_fd[i].events = POLLIN; } if (poll(poll_fd, _fd_client->size(), 0) < 0) assert(0); for (unsigned int i = 0; i < _fd_client->size(); ++i) if (poll_fd[i].revents != 0) { unsigned char sig = 0; unsigned int length = 0; do { errno = 0; length = read(poll_fd[i].fd, &sig, sizeof(unsigned char)); } while (errno == 4); if (errno) { perror(""); exit(errno); } if (length == 0) remove_client(poll_fd[i].fd); else if (sig == 42) { list_fd.push_back(poll_fd[i].fd); std::cout << "Reception signal sur le file descriptor :" << poll_fd[i].fd << std::endl; } else { std::cout << "Erreur de reception sur le file descriptor :" << poll_fd[i].fd << std::endl; exit(2); } poll_fd[i].revents = 0; } } void send_signal(const int& fd) { unsigned char sig = 42; write(fd, &sig, sizeof(unsigned char)); } void start_signal() { struct sigaction alarm; alarm.sa_handler = signal_alarm; alarm.sa_flags = 0; sigemptyset(&(alarm.sa_mask)); sigaddset(&(alarm.sa_mask), SIGALRM); sigaction(SIGALRM, &alarm, 0); ualarm(1, 100000); } template void send_data(const int& fd, const Data& data) { data.send(fd); } template void send_data(const Data& data, const std::list& fd_client) { std::list::const_iterator fd = fd_client.begin(); for (; fd != fd_client.end(); ++fd) data.send(*fd); } template void received_data(Data& data, const std::list& fd_client) { std::list::const_iterator fd = fd_client.begin(); for (; fd != fd_client.end(); ++fd) data.receive(*fd); } void accept_client(const int& fd) { std::cout << "Client connected on file descriptor: " << fd << std::endl; _fd_client->push_back(fd); } int get_fd() const { return (_fd); } int get_port() const { return (_port); } std::list* get_list_fd() const { return (_fd_client); } unsigned int get_nb_client() const { return (_fd_client->size()); } private: std::list *_fd_client; struct sockaddr_in *_sock_in; int _port; unsigned int _client_max; int _fd; }; #endif // SERVER_HH_