poll实现echo服务器的并发
代码实现
# include <stdio.h>
# include <string.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <stdlib.h>
# include <arpa/inet.h>
# include <sys/time.h>
# include <unistd.h>
# include <sys/poll.h> # define MAX_CLI 50 int clients[ MAX_CLI] ;
struct sockaddr_in clientaddr;
socklen_t len = sizeof ( clientaddr) ; int socket_create ( int port) { int fd; if ( ( fd = socket ( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror ( "socket" ) ; exit ( EXIT_FAILURE) ; } struct sockaddr_in addr; bzero ( & addr, sizeof ( addr) ) ; addr. sin_family = AF_INET; addr. sin_addr. s_addr = INADDR_ANY; addr. sin_port = htons ( port) ; if ( bind ( fd, ( struct sockaddr * ) & addr, sizeof ( addr) ) < 0 ) { perror ( "bind" ) ; exit ( EXIT_FAILURE) ; } if ( listen ( fd, 20 ) < 0 ) { perror ( "listen" ) ; exit ( EXIT_FAILURE) ; } return fd;
}
int recv_msg ( int fd, char * buff, int size) { int rsize = recv ( fd, buff, sizeof ( char ) * size, 0 ) ; if ( rsize <= 0 ) { if ( rsize == 0 ) return 0 ; return - 1 ; } printf ( "Recv : %s\n" , buff) ; return 1 ;
} int send_msg ( int fd, char * buff, int size) { int ssize = send ( fd, buff, sizeof ( char ) * size, 0 ) ; if ( ssize <= 0 ) { if ( ssize == 0 ) return 0 ; return - 1 ; } printf ( "Send success!\n" ) ; return 1 ;
} void echo_work ( int server_listen) { struct pollfd fds[ MAX_CLI + 1 ] ; fds[ 0 ] . fd = server_listen; fds[ 0 ] . events = POLLIN; int max_fd = server_listen; while ( 1 ) { int ret = poll ( fds, MAX_CLI + 1 , - 1 ) ; if ( ret == - 1 ) { perror ( "poll" ) ; exit ( EXIT_FAILURE) ; } if ( fds[ 0 ] . revents & POLLIN) { int client_fd; if ( ( client_fd = accept ( server_listen, ( struct sockaddr * ) & clientaddr, & len) ) < 0 ) { perror ( "accept" ) ; exit ( EXIT_FAILURE) ; } printf ( "one client connect success!\n" ) ; for ( int i = 0 ; i < MAX_CLI; i++ ) { if ( clients[ i] == - 1 ) { clients[ i] = client_fd; break ; } } for ( int i = 1 ; i <= MAX_CLI; i++ ) { if ( clients[ i - 1 ] != - 1 ) { fds[ i] . fd = clients[ i - 1 ] ; fds[ i] . events = POLLIN; max_fd = fds[ i] . fd > max_fd ? fds[ i] . fd : max_fd; } } } for ( int i = 1 ; i <= MAX_CLI; i++ ) { if ( fds[ i] . revents & POLLIN) { char buff[ 1024 ] = { 0 } ; if ( recv_msg ( fds[ i] . fd, buff, 1024 ) <= 0 ) { printf ( "disconnect one client OR error!\n" ) ; close ( fds[ i] . fd) ; clients[ i - 1 ] = - 1 ; continue ; } if ( send_msg ( fds[ i] . fd, buff, 1024 ) <= 0 ) { printf ( "disconnect one client OR error!\n" ) ; close ( fds[ i] . fd) ; clients[ i - 1 ] = - 1 ; continue ; } } } } return ;
} int main ( ) { int server_listen; if ( ( server_listen = socket_create ( 8080 ) ) < 0 ) { perror ( "socket_create" ) ; exit ( EXIT_FAILURE) ; } for ( int i = 0 ; i < MAX_CLI; i++ ) clients[ i] = - 1 ; echo_work ( server_listen) ; return 0 ;
}
运行效果