回射客户端服务器epoll( echo client && server improved by epoll function )
2015-11-11 00:41
477 查看
select :
1.The file descriptors that one process open is limited.
2.FD_SETSIZE
poll : The file descriptors that one process open is limited.
ulimit -n number
The file descriptors that the system run is limited with the memory.
the common points :
The kernel needs to traverse all of the file descriptors until it found the file descriptor with event occurrence. But when the number of file descriptor grows significantly , the efficiency of select function and poll function will decline heavily.So we
use another strategy , that's epoll.
Client :
1.The file descriptors that one process open is limited.
2.FD_SETSIZE
poll : The file descriptors that one process open is limited.
ulimit -n number
The file descriptors that the system run is limited with the memory.
the common points :
The kernel needs to traverse all of the file descriptors until it found the file descriptor with event occurrence. But when the number of file descriptor grows significantly , the efficiency of select function and poll function will decline heavily.So we
use another strategy , that's epoll.
Client :
/************************************************************************ >file name : 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> #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 ; } int main () { 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") ; } printf ("connected already\n") ; struct sockaddr_in localaddr ; socklen_t addrlen = sizeof(localaddr) ; if ( getsockname ( sock , ( struct sockaddr *) &localaddr , &addrlen ) < 0 ) { ERR_EXIT ("getsockname") ; } printf ("local_ip = %s local_port = %d\n" , inet_ntoa (localaddr.sin_addr ) , ntohs(localaddr.sin_port) ) ; struct sockaddr_in peeraddr ; socklen_t peerlen = sizeof(peeraddr) ; if ( getpeername ( sock , ( struct sockaddr * ) &peeraddr , &peerlen ) < 0 ) { ERR_EXIT ("getpeername") ; } printf ("peer_ip = %s peer_port = %d\n" , inet_ntoa (peeraddr.sin_addr ) , ntohs(peeraddr.sin_port) ) ; 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) int ret = readline ( sock , recvbuf , sizeof(recvbuf) ) ; if ( -1 == ret ) { ERR_EXIT ("readline") ; } else if ( 0 == ret ) //may interrupted by signal { printf ("clien________ close\n") ; break ; } fputs ( recvbuf , stdout ) ; memset ( sendbuf , 0 , sizeof(sendbuf) ) ; memset ( recvbuf , 0 , sizeof(recvbuf) ) ; } close ( sock ) ; return 0 ; }Server(write with c++ , cpp file ):
#include <stdio.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/epoll.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <arpa/inet.h> #include <unistd.h> #include <vector> #include <algorithm> #include <signal.h> typedef std::vector<struct epoll_event> EventList ; #define ERR_EXIT(m) \ do \ { \ perror(m) ; \ exit(EXIT_FAILURE) ; \ }while(0) void activate_nonblock ( int fd ) { int ret ; int flags = fcntl (fd , F_GETFL ) ; if ( -1 == flags ) { ERR_EXIT("fcntl\n") ; } flags |= O_NONBLOCK ; ret = fcntl(fd , F_SETFL , flags ) ; if ( -1 == ret ) { ERR_EXIT ("fcntl") ; } } ssize_t readn ( int fd , void *buf , size_t count ) { size_t nleft ; nleft = count ; ssize_t nread ; char *bufp = (char*) buf ; while( nleft > 0 ) { if ( ( nread = read ( fd , bufp , nleft ) ) < 0 ) { if ( EINTR == errno ) { continue ; } return -1 ; } else if ( 0 == nread ) { 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 = (char*) buf ; while( nleft > 0 ) { if ( ( nwritten= write ( fd , bufp , nleft ) ) < 0 ) { if ( EINTR == errno ) { continue ; } return -1 ; } else if ( 0 == nwritten ) { 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 ) ; if ( -1 == ret && EINTR == errno ) { continue ; } return ret ; } } ssize_t readline ( int sockfd , void *buf , size_t maxline ) { int ret ; int nread ; char *bufp = ( char * ) buf ; int nleft ; nleft = maxline ; while ( 1 ) { ret = recv_peek ( sockfd , bufp , nleft ) ; if ( ret < 0 ) { return ret ; } else if ( 0 == ret ) { 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 ) { exit(EXIT_FAILURE ) ; } nleft -= nread ; bufp += nread ; } return -1 ; } void handle_sigchld ( int sig ) { while( waitpid ( -1 , NULL , WNOHANG ) > 0 ) ; } void handle_sigpipe ( int sig ) { printf ("recv a sig = %d\n" , sig ) ; } int main (void) { int count ; count = 0 ; signal ( SIGPIPE , handle_sigpipe ) ; signal ( SIGCHLD , handle_sigchld ) ; 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) ; int on = 1 ; if ( setsockopt ( listenfd , SOL_SOCKET , SO_REUSEADDR , &on , sizeof(on) ) < 0 ) { ERR_EXIT("setsockopt") ; } if ( bind ( listenfd , ( struct sockaddr*) &servaddr , sizeof(servaddr) ) < 0 ) { ERR_EXIT("bind") ; } if ( listen( listenfd , SOMAXCONN ) < 0 ) { ERR_EXIT("listen") ; } std::vector<int>clients ; int epollfd ; epollfd = epoll_create1(EPOLL_CLOEXEC) ; //epollfd = epoll_create1(0) ; //EPOLL_CLOEXEC when the process is replaced , the file descriptor will be closed. struct epoll_event event ; event.data.fd = listenfd ; event.events = EPOLLIN | EPOLLET ; //EPOLLET edge triggered flip-flop,the default(EPOLLLT) is master-slave flip flop. epoll_ctl ( epollfd , EPOLL_CTL_ADD , listenfd , &event ) ; EventList events(16) ; struct sockaddr_in peeraddr ; socklen_t peerlen ; int conn ; int nready ; while ( 1 ) { nready = epoll_wait ( epollfd , &(*events.begin()) , static_cast<int>(events.size()) , -1 ) ; // -1 means wait all the time until there is an event . if ( -1 == nready ) { if ( EINTR == errno ) { continue ; } ERR_EXIT("epoll_wait") ; } if ( 0 == nready ) { continue ; } if ( ( size_t ) nready == events.size() ) // not big enough , resize ... { events.resize(events.size()*2) ; } int i ; for ( i = 0 ; i < nready ; i ++ ) { if ( events[i].data.fd == listenfd ) { struct sockaddr_in peeraddr ; socklen_t peerlen ; peerlen = sizeof(peeraddr) ; conn = accept ( listenfd , ( struct sockaddr*) &peeraddr , &peerlen ) ; //conn = accept ( listenfd , NULL , NULL ) ; if ( -1 == conn ) { ERR_EXIT("accept\n ") ; } printf("ip = %s port = %d\n" , inet_ntoa(peeraddr.sin_addr) , ntohs(peeraddr.sin_port) ) ; printf ("count = %d\n" , ++count) ; clients.push_back(conn) ; activate_nonblock(conn) ; event.data.fd = conn ; event.events = EPOLLIN|EPOLLET ; epoll_ctl ( epollfd , EPOLL_CTL_ADD , conn , &event ) ; } else if ( events[i].events & EPOLLIN ) { conn = events[i].data.fd ; if ( conn < 0 ) { continue ; } char recvbuf[1024] = {0} ; int ret = readline(conn , recvbuf , 1024) ; if ( -1 == ret ) { ERR_EXIT("readline") ; } if ( 0 == ret ) { printf ("client close\n") ; close(conn) ; event = events[i] ; epoll_ctl ( epollfd , EPOLL_CTL_DEL , conn , &event ) ; clients.erase(std::remove(clients.begin() , clients.end() , conn) , clients.end()) ; } fputs ( recvbuf , stdout ) ; writen(conn , recvbuf , strlen(recvbuf)) ; } } } return 0 ; }
相关文章推荐
- redis3.0集群实现方案
- Android图片显示之通过handler机制实现数据通讯
- STM32入门学习之USART中断(STM32F030F4P6基于CooCox IDE)
- 记第一次的破解经历
- nodeJS文件路径总结
- linux文件管理
- The connection to adb is down, and a severe error has occured.问题解决方法小结
- 【Alpha发布】网站已经正式发布!
- NoSQL你知多少?
- An internal error occurred during: "Launching ZMS on MyEclipse Tomcat". java.lang.NullPointerExcepti
- 在ThoughtWorks工作这几年我学到了什么?
- 请求权限被拒绝的检测及处理
- HDU 2955 Robberies(01背包变形)
- Struts2中Action接收参数的方法
- LeetCode -- Sliding Window Maximum
- 实现鼠标手写板(.Net)
- SAP 数据复制工具
- poj 2154 Color polya计数+欧拉优化
- Leetcode -- Single Number II
- 图片高斯模糊