select的TCP服务器模型
服务器端
# include <head.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <unistd.h>
# include <sys/select.h>
# include <sys/time.h> # define PORT 6666
# define IP "192.168.122.120"
int main ( int argc, const char * argv[ ] )
{ int sfd = socket ( AF_INET, SOCK_STREAM, 0 ) ; if ( sfd < 0 ) { ERRO_MES ( "socket" ) ; return - 1 ; } printf ( "sfd = %d\n" , sfd) ; struct sockaddr_in sin; sin. sin_family = AF_INET; sin. sin_port = htons ( PORT) ; sin. sin_addr. s_addr = inet_addr ( IP) ; if ( bind ( sfd, ( struct sockaddr * ) & sin, sizeof ( sin) ) < 0 ) { ERRO_MES ( "bind" ) ; return - 1 ; } printf ( "bind success\n" ) ; if ( listen ( sfd, 10 ) < 0 ) { ERRO_MES ( "listen" ) ; return - 1 ; } printf ( "listen success\n" ) ; int reuse = 1 ; if ( setsockopt ( sfd, SOL_SOCKET, SO_REUSEADDR, & reuse, sizeof ( reuse) ) < 0 ) { ERRO_MES ( "setsockopt" ) ; return - 1 ; } printf ( "允许端口快速重用成功\n" ) ; struct sockaddr_in cin; socklen_t addrlen = sizeof ( cin) ; struct sockaddr_in saveCin[ 1024 - 3 ] ; fd_set readfds, tempfds; FD_ZERO ( & readfds) ; FD_ZERO ( & tempfds) ; FD_SET ( sfd, & readfds) ; FD_SET ( 0 , & readfds) ; int maxfd = sfd; int s_res = - 1 ; char buf[ 128 ] = "" ; ssize_t res = 0 ; int newfd = - 1 ; while ( 1 ) { tempfds = readfds; s_res = select ( maxfd+ 1 , & tempfds, NULL , NULL , NULL ) ; if ( s_res < 0 ) { ERRO_MES ( "select" ) ; return - 1 ; } else if ( 0 == s_res) { printf ( "超时操作\n" ) ; break ; } for ( int i= 0 ; i<= maxfd; i++ ) { if ( FD_ISSET ( i, & tempfds) == 0 ) continue ; if ( 0 == i) { printf ( "触发键盘输入事件\n" ) ; fgets ( buf, sizeof ( buf) , stdin ) ; buf[ strlen ( buf) - 1 ] = 0 ; printf ( ": %s\n" , buf) ; } else if ( sfd == i) { printf ( "触发客户端连接事件\n" ) ; newfd = accept ( sfd, ( struct sockaddr * ) & cin, & addrlen) ; if ( newfd < 0 ) { ERRO_MES ( "accept" ) ; return - 1 ; } printf ( "[%s : %d] newfd = %d,客户端链接成功\n" , \inet_ntoa ( cin. sin_addr) , ntohs ( cin. sin_port) , newfd) ; saveCin[ newfd- 3 ] = cin; FD_SET ( newfd, & readfds) ; maxfd = newfd> sfd ? newfd : sfd; } else { printf ( "触发客户端交互事件\n" ) ; bzero ( buf, sizeof ( buf) ) ; res = recv ( i, buf, sizeof ( buf) , 0 ) ; if ( res < 0 ) { ERRO_MES ( "recv" ) ; return - 1 ; } else if ( 0 == res) { printf ( "[%s : %d] newfd = %d,客户下线\n" , \inet_ntoa ( saveCin[ i- 3 ] . sin_addr) , ntohs ( saveCin[ i- 3 ] . sin_port) , i) ; close ( i) ; FD_CLR ( i, & readfds) ; while ( FD_ISSET ( maxfd, & readfds) == 0 && maxfd-- >= 0 ) ; continue ; } printf ( "[%s : %d] newfd :%d\t buf = %s\n" \, inet_ntoa ( saveCin[ i- 3 ] . sin_addr) , ntohs ( saveCin[ i- 3 ] . sin_port) , i, buf) ; strcat ( buf, "----" ) ; if ( send ( newfd, buf, sizeof ( buf) , 0 ) < 0 ) { ERRO_MES ( "send" ) ; return - 1 ; } printf ( "send success\n" ) ; } } } close ( sfd) ; close ( newfd) ; return 0 ;
}
客户端
# include <head.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <unistd.h>
# include <sys/select.h>
# include <sys/time.h> # define PORT 6666
# define IP "192.168.122.120"
int main ( int argc, const char * argv[ ] )
{ int cfd = socket ( AF_INET, SOCK_STREAM, 0 ) ; if ( cfd < 0 ) { ERRO_MES ( "socket" ) ; return - 1 ; } printf ( "cfd = %d\n" , cfd) ; struct sockaddr_in sin; sin. sin_family = AF_INET; sin. sin_port = htons ( PORT) ; sin. sin_addr. s_addr = inet_addr ( IP) ; if ( connect ( cfd, ( struct sockaddr * ) & sin, sizeof ( sin) ) < 0 ) { ERRO_MES ( "connect" ) ; return - 1 ; } printf ( "连接成功\n" ) ; fd_set readfds, tempfds; FD_ZERO ( & readfds) ; FD_ZERO ( & tempfds) ; FD_SET ( 0 , & readfds) ; FD_SET ( cfd, & readfds) ; char buf[ 128 ] = "" ; ssize_t res = 0 ; int s_res = - 1 ; int maxfd = cfd; while ( 1 ) { tempfds = readfds; s_res = select ( maxfd+ 1 , & tempfds, NULL , NULL , NULL ) ; if ( s_res < 0 ) { ERRO_MES ( "select" ) ; return - 1 ; } else if ( 0 == s_res) { printf ( "time out...\n" ) ; break ; } if ( FD_ISSET ( 0 , & tempfds) ) { printf ( "触发键盘输入事件\n" ) ; bzero ( buf, sizeof ( buf) ) ; fgets ( buf, sizeof ( buf) , stdin ) ; buf[ strlen ( buf) - 1 ] = 0 ; printf ( ": %s\n" , buf) ; if ( send ( cfd, buf, sizeof ( buf) , 0 ) < 0 ) { ERRO_MES ( "send" ) ; return - 1 ; } printf ( "send success\n" ) ; } if ( FD_ISSET ( cfd, & tempfds) ) { printf ( "触发服务器交互事件\n" ) ; bzero ( buf, sizeof ( buf) ) ; res = recv ( cfd, buf, sizeof ( buf) , 0 ) ; if ( res < 0 ) { ERRO_MES ( "recv" ) ; return - 1 ; } else if ( 0 == res) { printf ( "[%s : %d] cfd = %d,客户下线\n" , IP, PORT, cfd) ; break ; } printf ( "[%s : %d] cfd :%d\t buf = %s\n" , IP, PORT, cfd, buf) ; } } close ( cfd) ; return 0 ;
}
poll客户端
# include <head.h>
# include <arpa/inet.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <poll.h>
# include <unistd.h> # define PORT 6666
# define IP "192.168.122.120"
int main ( int argc, const char * argv[ ] )
{ int cfd = socket ( AF_INET, SOCK_STREAM, 0 ) ; if ( cfd < 0 ) { ERRO_MES ( "socket" ) ; return - 1 ; } printf ( "cfd = %d\n" , cfd) ; struct sockaddr_in sin; sin. sin_family = AF_INET; sin. sin_port = htons ( PORT) ; sin. sin_addr. s_addr = inet_addr ( IP) ; if ( connect ( cfd, ( struct sockaddr * ) & sin, sizeof ( sin) ) < 0 ) { ERRO_MES ( "connect" ) ; return - 1 ; } printf ( "connect success\n" ) ; struct pollfd fds[ 2 ] ; fds[ 0 ] . fd = 0 ; fds[ 0 ] . events = POLLIN; fds[ 1 ] . fd = cfd; fds[ 1 ] . events = POLLIN; char buf[ 128 ] = "" ; ssize_t res = 0 ; int p_res = - 1 ; while ( 1 ) { p_res = poll ( fds, 2 , - 1 ) ; if ( p_res < 0 ) { ERRO_MES ( "poll" ) ; return - 1 ; } else if ( 0 == p_res) { printf ( "time out...\n" ) ; break ; } if ( ( fds[ 0 ] . revents & POLLIN) != 0 ) { printf ( "触发键盘输入事件\n" ) ; bzero ( buf, sizeof ( buf) ) ; fgets ( buf, sizeof ( buf) , stdin ) ; buf[ strlen ( buf) - 1 ] = 0 ; if ( send ( cfd, buf, sizeof ( buf) , 0 ) < 0 ) { ERRO_MES ( "send" ) ; return - 1 ; } printf ( "send success\n" ) ; } if ( fds[ 1 ] . revents & POLLIN) { printf ( "触发服务器交互事件\n" ) ; bzero ( buf, sizeof ( buf) ) ; res = recv ( cfd, buf, sizeof ( buf) , 0 ) ; if ( res < 0 ) { ERRO_MES ( "recv" ) ; return - 1 ; } else if ( 0 == res) { printf ( "[%s : %d] cfd= %d 服务器掉线\n" , IP, PORT, cfd) ; break ; } printf ( "[%s : %d] cfd= %d : %s\n" , IP, PORT, cfd, buf) ; } } close ( cfd) ; return 0 ;
}