标签:
1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <arpa/inet.h> 5 #include <assert.h> 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <errno.h> 9 #include <string.h> 10 #include <fcntl.h> 11 #include <stdlib.h> 12 #include <sys/epoll.h> 13 #include <pthread.h> 14 #include <libgen.h> 15 #include <strings.h> 16 #define MAX_EVENT_NUMBER 1024 17 #define BUFFER_SIZE 10 18 19 int setnonblocking( int fd ) 20 { 21 int old_option = fcntl( fd, F_GETFL ); 22 int new_option = old_option | O_NONBLOCK; 23 fcntl( fd, F_SETFL, new_option ); 24 return old_option; 25 } 26 void addfd( int epollfd, int fd, int enable_et ) 27 { 28 struct epoll_event event; 29 event.data.fd = fd; 30 event.events = EPOLLIN; 31 if( enable_et ) 32 { 33 event.events |= EPOLLET; 34 } 35 epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); 36 setnonblocking( fd ); 37 } 38 39 void lt( struct epoll_event * events, int number, int epollfd, int listenfd ) 40 { 41 char buf[ BUFFER_SIZE ]; 42 for ( int i = 0; i < number; i++ ) 43 { 44 int sockfd = events[i].data.fd; 45 if ( sockfd == listenfd ) 46 { 47 struct sockaddr_in client_address; 48 socklen_t client_addrlength = sizeof( client_address ); 49 int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength ); 50 addfd( epollfd, connfd, 0 ); 51 } 52 else if ( events[i].events & EPOLLIN ) 53 { 54 printf( "event trigger once\n" ); 55 memset( buf, ‘\0‘, BUFFER_SIZE ); 56 int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 ); 57 if( ret <= 0 ) 58 { 59 close( sockfd ); 60 continue; 61 } 62 printf( "get %d bytes of content: %s\n", ret, buf ); 63 } 64 else 65 { 66 printf( "something else happened \n" ); 67 } 68 } 69 } 70 71 void et( struct epoll_event *events, int number, int epollfd, int listenfd ) 72 { 73 char buf[ BUFFER_SIZE ]; 74 for ( int i = 0; i < number; i++ ) 75 { 76 int sockfd = events[i].data.fd; 77 if ( sockfd == listenfd ) 78 { 79 struct sockaddr_in client_address; 80 socklen_t client_addrlength = sizeof( client_address ); 81 int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength ); 82 addfd( epollfd, connfd, 1 ); 83 } 84 else if ( events[i].events & EPOLLIN ) 85 { 86 printf( "event trigger once\n" ); 87 while( 1 ) 88 { 89 memset( buf, ‘\0‘, BUFFER_SIZE ); 90 int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 ); 91 if( ret < 0 ) 92 { 93 if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) 94 { 95 printf( "read later\n" ); 96 break; 97 } 98 close( sockfd ); 99 break; 100 } 101 else if( ret == 0 ) 102 { 103 close( sockfd ); 104 } 105 else 106 { 107 108 printf( "get %d bytes of content: %s\n", ret, buf ); 109 110 } 111 } 112 } 113 else 114 { 115 printf( "something else happened \n" ); 116 } 117 } 118 } 119 120 int main( int argc, char* argv[] ) 121 { 122 if( argc <= 2 ) 123 { 124 printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 125 return 1; 126 } 127 const char* ip = argv[1]; 128 int port = atoi( argv[2] ); 129 130 int ret = 0; 131 struct sockaddr_in address; 132 bzero( &address, sizeof( address ) ); 133 address.sin_family = AF_INET; 134 inet_pton( AF_INET, ip, &address.sin_addr ); 135 address.sin_port = htons( port ); 136 137 int listenfd = socket( PF_INET, SOCK_STREAM, 0 ); 138 assert( listenfd >= 0 ); 139 140 ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); 141 assert( ret != -1 ); 142 143 ret = listen( listenfd, 5 ); 144 assert( ret != -1 ); 145 146 struct epoll_event events[MAX_EVENT_NUMBER]; 147 int epollfd = epoll_create( 5 ); 148 assert( epollfd != -1 ); 149 addfd(epollfd,listenfd,1); 150 151 while( 1 ) 152 { 153 int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 ); 154 if (ret < 0) 155 { 156 printf( "epoll failure\n" ); 157 break; 158 } 159 160 // lt( events, ret, epollfd, listenfd ); 161 et( events, ret, epollfd, listenfd ); 162 } 163 164 close( listenfd ); 165 return 0; 166 }
但是奇怪的是为什么总是接受的数据多两个呢?而且
我观察上面的代码,第90行int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 ),至第108行 printf( "get %d bytes of content: %s\n", ret, buf );
可以看出估计是把enter键包含进去了,所以多出两个字节!
上面是以ET模式在运行,下来我们用LT模式来执行
标签:
原文地址:http://www.cnblogs.com/leijiangtao/p/4454126.html