回射客户端服务器select 修改版[1]( echo client && server improved by select function)
来源:互联网 发布:进程调度算法流程图 编辑:程序博客网 时间:2024/05/22 18:47
Function :
Compared with the former edition , we add select function to realise I/O multiplexing which let client can monitor the standard input and readable event from the socket. We mainly changed the code of the client.
Server:
/************************************************************************ > filename: echoserv2.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Thu 29 Oct 16:38:57 2015 ************************************************************************/#include <signal.h>#include <stdio.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/wait.h>#define ERR_EXIT(m) \do \{\perror(m) ;\exit(EXIT_FAILURE) ;\}while(0) //ssize_t the signed integer , size_t the unsigned integer ssize_t readn ( int fd , void *buf , size_t count ) //encapsulate like read function {size_t nleft = count ;ssize_t nread ;char *bufp ;bufp = ( char *) buf ;while ( nleft > 0 ) {//nread = read ( fd , bufp , nleft ) ;//printf ("nread = %d\n" , nread ) ;if ( (nread = read ( fd , bufp , nleft )) < 0 ) {if ( EINTR == errno ) // interrupted by the signal , we don't think this occasion is a mistake {continue ;}return -1 ; //failure } else if ( 0 == nread ) // peer close {return count - nleft ; }bufp += nread ;nleft -= nread ;}return count ;}ssize_t writen ( int fd ,const void *buf , size_t count ) {size_t nleft = count ;ssize_t nwritten ;char * bufp ;bufp = (char*) buf ;while ( nleft > 0 ) {if ( ( nwritten = write ( fd , bufp , nleft ) ) < 0 ) {if ( EINTR == errno ) {continue ;}return -1 ;}else if ( 0 == nwritten ) // like nothing happened to write function {continue ;}bufp += nwritten ;nleft -= nwritten ;}return count ;}ssize_t recv_peek ( int sockfd , void *buf , size_t len ) {while ( 1 ) {int ret = recv ( sockfd , buf , len , MSG_PEEK ) ; //only let buf read the data from sockfd but not remove the data from that sockfd(socket) //in comparison with read function it receive the data and remove the data in the socket if ( -1 == ret && EINTR == errno ) {continue ;//interrupted by signal }return ret ;}} ssize_t readline ( int sockfd , void *buf , size_t maxline ) {int ret ;int nread ;char *bufp ;bufp = (char*) buf ;int nleft ;nleft = maxline ;while (1 ) {ret = recv_peek ( sockfd, bufp , nleft ) ;if ( ret < 0 ) //failure {return ret ;}else if ( 0 == ret )// peer closed {return ret ;}nread = ret ;int i ;for ( i = 0 ; i < nread ; i ++ ) {if ( '\n' == bufp[i]) {ret = readn (sockfd,bufp , i+1) ;if ( ret != i + 1 ) {exit(EXIT_FAILURE) ;}return ret ;}}if ( nread > nleft ) // the data that we read(nread) can't be more than the real data in the socket {exit ( EXIT_FAILURE ) ;}nleft -= nread ;ret = readn ( sockfd , bufp , nread ) ; // read n characters from the socket ( don't contain '\n') if ( ret != nread ) {exit(EXIT_FAILURE ) ;}bufp += nread ;}return -1 ;}void echo_serv ( int conn ) { char recvbuf[1024] ; while(1) { memset ( recvbuf , 0 , sizeof(recvbuf) ) ; int ret = readline ( conn , recvbuf , sizeof(recvbuf) ) ; if ( -1 == ret ) { ERR_EXIT("readline") ; }if ( 0 == ret ) {//ERR_EXIT ("client close\n") ;printf("client close\n") ;break ;}fputs ( recvbuf , stdout ) ;writen ( conn , recvbuf , strlen(recvbuf) ) ; }}void handle_sigchld ( int sig ) {//wait ( NULL ) ; //call wait function to catch the process of the son /*ther will be a problem to call wait if there many sons' processes , wait function can not wait all the sons' processes to quit. Another saying is that wait funciton can not guarantee that there is clear of zombie processes when many sons's processes exist. wait function only wait for the first son process to quit ,then wait will quit immediately.In order to improve this performance , we use waitpid() to change. *///static i = 0 ;//printf ("i = %d\n",++i ) ;while ( waitpid(-1,NULL,WNOHANG) > 0 ) ;/*-1 means all of the son process will quit,WNOHANG means wait no hang no hang means when there is no son process , waitpid will return -1 :*/}int main () {signal ( SIGCHLD , handle_sigchld ) ;//signal ( SIGCHLD , SIG_IGN ) ; /* neglect the signal of SIGCHLD to avoid zombie process which happened to the server when the client quit , but the server still keeps listening.*/ int listenfd ;if (( listenfd = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP )) < 0 ) {ERR_EXIT("socket") ;}struct sockaddr_in servaddr ;memset ( & servaddr , 0 , sizeof(servaddr ) ) ;servaddr.sin_family = AF_INET ;servaddr.sin_port = htons (5188) ;servaddr.sin_addr.s_addr = htonl(INADDR_ANY) ;//INTADDR_ANY == 0//other two means to change the host address to network address //servaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ; //inet_aton("127.0.0.1" , &servaddr.sin_addr) ;//set out the bind has already used by SO_REUSEADDR int on = 1 ;int opt ;if (( opt = setsockopt (listenfd ,SOL_SOCKET , SO_REUSEADDR, &on , sizeof(on) )) < 0 ){ERR_EXIT("setsocketopt") ;}if ( bind ( listenfd , (struct sockaddr * ) &servaddr , sizeof(servaddr )) < 0 ) {ERR_EXIT("bind") ;}if ( listen ( listenfd , SOMAXCONN) < 0 ) {ERR_EXIT("listen") ;}struct sockaddr_in peeraddr ;socklen_t peerlen = sizeof(peeraddr) ;int conn ;while ( 1 ) {if ( (conn = accept ( listenfd , ( struct sockaddr * )&peeraddr , &peerlen )) < 0 ){ERR_EXIT("accept") ;}// print the client's address and ip 'printf ("ip = %s port = %d\n", inet_ntoa(peeraddr.sin_addr) ,ntohs(peeraddr.sin_port) ) ;int pid ;pid = fork() ; // creat the child process to set out the multi-connection from clients if ( -1 == pid ) {ERR_EXIT ("fork") ;}if ( 0 == pid ) {close (listenfd) ; // the son's pid didn't need to process the listen , so we close listenfd ;echo_serv (conn) ;exit(EXIT_SUCCESS) ;}else {close (conn) ; // the father's pid didn't need to process the acceept ,so we close conn '}}return 0 ;}
Client(modified) :
/************************************************************************ > filename : echocli.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Thu 29 Oct 16:38:57 2015 ************************************************************************/#include <stdio.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <signal.h>#define ERR_EXIT(m) \do \{\perror(m) ;\exit(EXIT_FAILURE) ;\}while(0) //ssize_t signed integer size_t unsigned integer ssize_t readn ( int fd , void *buf , size_t count ) // encapsulate readn as the function of read {size_t nleft = count ;ssize_t nread ;char *bufp ;bufp = ( char *) buf ;//printf ("nleft = %d\n" , nleft ) ;while ( nleft > 0 ) {//printf ("nleft = %d\n" , nleft ) ;nread = read ( fd , bufp , nleft ) ;// printf ("nread = %d\n" , nread ) ;if( nread < 0 ){if ( errno == EINTR ) // interrupted by signal , we don't think this occasion is not right {continue ;}return -1 ;}else if ( 0 == nread ) //peer closed {return count - nleft ;//break ; }//printf ("nreaad = %d\n" , nread ) ;bufp += nread ;nleft -= nread ;}return count ;}ssize_t writen ( int fd , const void *buf ,size_t count ) {size_t nleft = count ;ssize_t nwritten ;char *bufp ;bufp = ( char * ) buf ;while ( nleft > 0 ) {if ( ( nwritten = write ( fd , bufp , nleft ) ) < 0 ) {if ( errno == EINTR ) // just like the occasion in writen{continue ; }return -1 ;}else if ( 0 == nwritten ) // if 0 == nread , like nothing happened to write ... {continue ;}bufp += nwritten ;nleft -= nwritten ; }return count ;}ssize_t recv_peek ( int sockfd , void *buf , size_t len ) {while ( 1 ) {int ret = recv ( sockfd , buf , len , MSG_PEEK ) ; //only let buf read the data from sockfd but not remove the data from that sockfd(socket) //in comparison with read function it receive the data and remove the data in the socket if ( -1 == ret && EINTR == errno ) {continue ;//interrupted by signal }return ret ;}} ssize_t readline ( int sockfd , void *buf , size_t maxline ) {int ret ;int nread ;char *bufp ;bufp = (char*) buf ;int nleft ;nleft = maxline ;while (1 ) {ret = recv_peek ( sockfd, bufp , nleft ) ;if ( ret < 0 ) //failure {return ret ;}else if ( 0 == ret )// peer closed {return ret ;}nread = ret ;int i ;for ( i = 0 ; i < nread ; i ++ ) {if ( '\n' == bufp[i]) {ret = readn (sockfd,bufp , i+1) ;if ( ret != i + 1 ) {exit(EXIT_FAILURE) ;}return ret ;}}if ( nread > nleft ) // the data that we read(nread) can't be more than the real data in the socket {exit ( EXIT_FAILURE ) ;}nleft -= nread ;ret = readn ( sockfd , bufp , nread ) ; // read n characters from the socket ( don't contain '\n') if ( ret != nread ) {exit(EXIT_FAILURE ) ;}bufp += nread ;}return -1 ;}void echo_cli ( int sock ) {/*char sendbuf[1024]={0} ; char recvbuf[1024]={0} ; memset ( sendbuf , 0 , sizeof(sendbuf) ) ; memset ( recvbuf , 0 , sizeof(recvbuf) ) ; int n ; while( fgets ( sendbuf , sizeof(sendbuf) , stdin ) != NULL ) { //fgets get the data with '\n' in default // writen ( sock , sendbuf ,strlen(sendbuf) ) ; // the former 4 bytes and the real data(n)//write ( sock , sendbuf , 1 ) ;//write ( sock , sendbuf + 1 , strlen(sendbuf) -1 ) ; iwriten ( sock , sendbuf, strlen(sendbuf) ) ; int ret = readline ( sock , recvbuf , sizeof(recvbuf) ) ; if ( -1 == ret ) { ERR_EXIT ("readline") ; } else if ( 0 == ret ) //may interrupted by signal { printf ("server________ close\n") ; break ; } fputs ( recvbuf , stdout ) ; memset ( sendbuf , 0 , sizeof(sendbuf) ) ; memset ( recvbuf , 0 , sizeof(recvbuf) ) ; }close(sock) */fd_set rset ;FD_ZERO ( &rset ) ;int nready ;int maxfd ;int fd_stdin = fileno(stdin) ; // STD_FILENO == 0 but stdin may be redirected. so we don't use STD_FILENO if ( fd_stdin > sock ) {maxfd = fd_stdin ;}else {maxfd = sock ; }char sendbuf[1024] = {0} ;char recvbuf[1024] = {0} ; memset ( recvbuf , 0 , sizeof(recvbuf) ) ;while(1) {FD_SET ( fd_stdin , &rset ) ;FD_SET ( sock , &rset ) ;nready = select ( maxfd + 1 , &rset , NULL , NULL , NULL ) ;if ( -1 == nready ) {ERR_EXIT("select") ;}if ( 0 == nready ) {continue ;}if ( FD_ISSET ( sock , &rset ) ) {int ret = readline ( sock , recvbuf , sizeof ( recvbuf ) ) ;if ( -1 == ret ) {ERR_EXIT("redline") ;}else if ( 0 == ret ) {printf ("server_____close\n") ;break ;}fputs ( recvbuf , stdout ) ;memset ( recvbuf , 0 , sizeof(recvbuf) ) ;}if ( FD_ISSET ( fd_stdin , &rset ) ) {if (fgets (sendbuf, sizeof(sendbuf) , stdin ) == NULL ){break ;} writen ( sock , sendbuf , strlen(sendbuf) ) ;memset ( sendbuf , 0 , sizeof(sendbuf) ) ;}}close(sock) ;}void handle_sigpipe ( int sig ) {printf ("recv a sig = %d\n" , sig ) ;}int main () {//signal ( SIGPIPE , handle_sigpipe ) ;isignal ( SIGPIPE , SIG_IGN ) ;int sock ;if (( sock= socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP )) < 0 ) {ERR_EXIT("socket") ;}struct sockaddr_in servaddr ;memset ( & servaddr , 0 , sizeof(servaddr) ) ;servaddr.sin_family = AF_INET ;servaddr.sin_port = htons (5188) ;//servaddr.sin_addr.s_addr = htonl(INADDR_ANY) ;servaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ;//inet_aton("127.0.0.1" , &servaddr.sin_addr) ; if ( connect ( sock , ( struct sockaddr * )& servaddr, sizeof(servaddr )) < 0 ){ERR_EXIT("connet") ;}echo_cli(sock) ;return 0 ;}
0 0
- 回射客户端服务器select 修改版[1]( echo client && server improved by select function)
- 回射客户端服务器select 修改版[2]( echo client && server improved by select function)
- 回射客户端服务器shutdown修改版( echo client && server improved by select shutdown )
- 回射客户端服务器epoll( echo client && server improved by epoll function )
- 回射客户端服务器UDP(echo client&&server based on UDP)
- TCP Echo Server(select)
- 基于select和epoll的Echo服务器与客户端编程
- 回射客户端服务器中僵尸进程的处理( the solution of zombie process in the echo client && server )
- TCP Server/Client, Select
- server.c客户端服务器select 赵超越
- CMU440-P0:Implementing a multi-client echo server(实现一个多客户端回显服务器)
- simple select echo server example
- select 实现 tcp echo 服务器
- wxpython select 聊天室server+client
- 回射-客户服务器 ( echo client-server ) [ Edition 1]
- 基于select模型的python echo server
- select--服务器与客户端 郑明莉
- server-client 服务器 客户端 李春玲
- sql 存储过程分页查询
- 基于Smack3.0.4+ Openfire3.10.2下学习开发IM(三)用户基础信息(VCard)
- js中(function(){…})()立即执行函数写法理解
- 个人经过多方查询所得关于懒加载的一些浅薄认识,及如何设置随机颜色,让个人界面变得多彩
- 找工作
- 回射客户端服务器select 修改版[1]( echo client && server improved by select function)
- js自执行函数的几种不同写法的比较
- 你应该知道的35个Jquey小技巧
- 51nod 1433 0和5
- 面试代码
- OBB文件和StorageManager类及.nomedia
- Lucene / Solr 开发经验
- xml文件配置报错问题
- 一个优秀的Java程序员必须了解的GC机制