TA的每日心情 | 开心 2021-12-13 21:45 |
---|
签到天数: 15 天 [LV.4]偶尔看看III
|
公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接。
1. 问题分析
首先在公司内部测试服务器上部署,使用LoadRunner做压力测试,能正常运行,然后那边的同事反馈该地方信号较差。考虑到接入的问题,有可能接入进程的FD资源耗尽,导致accept失败。推论的依据是对于TCP连接来说,如果客户端那边由于一些异常情况导致断网而未能向服务器发起FIN关闭消息,服务端这边若没有设置存活检测的话,该连接会存在(存活时间暂未测)。
2. 实验测试
这里简单地写了一个服务端的程序,主要功能是回应,即接受一个报文(格式:2Byte报文长度+报文内容),然后原封不动将报文内容发回客户端。

- 1 #include <stdio.h>
- 2 #include <sys/types.h>
- 3 #include <sys/socket.h>
- 4 #include <sys/epoll.h>
- 5 #include <unistd.h>
- 6 #include <pthread.h>
- 7 #include <stdlib.h>
- 8 #include <string.h>
- 9 #include <arpa/inet.h>
- 10
- 11 int g_epfd;
- 12
- 13 int InitServer( unsigned short port )
- 14 {
- 15 int nServerFd = socket( AF_INET, SOCK_STREAM, 0 );
- 16
- 17 struct sockaddr_in addr;
- 18 memset( &addr, 0, sizeof(addr) );
- 19
- 20 addr.sin_family = AF_INET;
- 21 addr.sin_port = htons( port );
- 22 addr.sin_addr.s_addr = 0;
- 23
- 24 if ( bind( nServerFd, (struct sockaddr *)&addr, sizeof(addr) ) <0 )
- 25 {
- 26 printf("bind error\n");
- 27 exit(-1);
- 28 }
- 29
- 30 if ( listen( nServerFd, 128 ) < 0 )
- 31 {
- 32 printf("listen error\n");
- 33 exit(-1);
- 34 }
- 35
- 36 return nServerFd;
- 37 }
- 38
- 39 int AddFd( int epfd, int nFd , int nOneShot)
- 40 {
- 41 struct epoll_event event;
- 42 memset( &event, 0, sizeof( event) );
- 43
- 44 event.data.fd = nFd;
- 45 event.events |= EPOLLIN | EPOLLRDHUP | EPOLLET;
- 46
- 47 if ( nOneShot ) event.events |= EPOLLONESHOT;
- 48
- 49 return epoll_ctl( epfd, EPOLL_CTL_ADD, nFd, &event );
- 50 }
- 51
- 52 int ResetOneShot( int epfd, int nFd )
- 53 {
- 54 struct epoll_event event;
- 55 memset( &event, 0, sizeof(event) );
- 56
- 57 event.data.fd = nFd;
- 58 event.events |= EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
- 59
- 60 return epoll_ctl( epfd, EPOLL_CTL_MOD, nFd, &event);
- 61 }
- 62
- 63 void * ReadFromClient( void * arg )
- 64 {
- 65 int nClientFd = (int)arg;
- 66 unsigned char buf[1024];
- 67 const int nBufSize = sizeof( buf );
- 68 int nRead;
- 69 int nTotal;
- 70 int nDataLen;
- 71
- 72 printf("ReadFromClient Enter\n");
- 73
- 74 if ( (nRead = read( nClientFd, buf, 2 )) != 2 )
- 75 {
- 76 printf("Read Data Len error\n");
- 77 pthread_exit(NULL);
- 78 }
- 79
- 80 nDataLen = *(unsigned short *)buf;
- 81 printf("nDataLen [%d]\n", nDataLen);
- 82 nDataLen = buf[0]*256 + buf[1];
- 83 printf("nDataLen [%d]\n", nDataLen);
- 84
- 85 nRead = 0;
- 86 nTotal = 0;
- 87 while( 1 )
- 88 {
- 89 nRead = read( nClientFd, buf + nRead, nBufSize );
- 90 if ( nRead < 0 )
- 91 {
- 92 printf("Read Data error\n");
- 93 pthread_exit( NULL );
- 94 }
- 95 nTotal += nRead;
- 96 if ( nTotal >= nDataLen )
- 97 {
- 98 break;
- 99 }
- 100 }
- 101 printf("nTotal [%d]\n", nTotal);
- 102
- 103 sleep(5);
- 104
- 105 int nWrite = write( nClientFd, buf, nTotal );
- 106 printf("nWrite[%d]\n", nWrite);
- 107
- 108 printf("Not Write ResetOneShot [%d]\n", ResetOneShot(g_epfd, nClientFd));
- 109
- 110 return NULL;
- 111 }
- 112
- 113 int main(int argc, char const *argv[])
- 114 {
- 115 int i;
- 116 int nClientFd;
- 117 pthread_t tid;
- 118 struct epoll_event events[1024];
- 119
- 120 int nServerFd = InitServer( 7777 );
- 121 if ( nServerFd < 0 )
- 122 {
- 123 perror( "nServerFd" );
- 124 exit(-1);
- 125 }
- 126
- 127 int epfd = epoll_create( 1024 );
- 128
- 129 g_epfd = epfd;
- 130
- 131 int nReadyNums;
- 132
- 133 if ( AddFd( epfd, nServerFd, 0 ) < 0 )
- 134 {
- 135 printf("AddFd error\n");
- 136 exit(-1);
- 137 }
- 138
- 139 while( 1 )
- 140 {
- 141 nReadyNums = epoll_wait( epfd, events, 1024, -1 );
- 142
- 143 if ( nReadyNums < 0 )
- 144 {
- 145 printf("epoll_wait error\n");
- 146 exit(-1);
- 147 }
- 148
- 149 for ( i = 0; i < nReadyNums; ++i)
- 150 {
- 151 if ( events[i].data.fd == nServerFd )
- 152 {
- 153 nClientFd = accept( nServerFd, NULL, NULL );
- 154
- 155 AddFd( epfd, nClientFd, 1 );
- 156
- 157 }else if ( events[i].events & EPOLLIN )
- 158 {
- 159 // Can be implemented by threadpool
- 160 //Read data from client
- 161 pthread_create( &tid, NULL, ReadFromClient, (void *)(events[i].data.fd) );
- 162
- 163 }else if ( events[i].events & EPOLLRDHUP )
- 164 {
- 165 //Close By Peer
- 166 printf("Close By Peer\n");
- 167 close( events[i].data.fd );
- 168 }else
- 169 {
- 170 printf("Some thing happened\n");
- 171 }
- 172
- 173 }
- 174 }
- 175
- 176 return 0;
- 177 }
复制代码

测试内容:
注:客户端IP: 192.168.10.108 服务器IP&Port: 192.168.10.110:7777
a. 客户端发送一个报文至服务端,然后断网。(这里对程序做了点改动,这次实验注释了write响应,防止write影响测试,后面一个实验会使用write)。
http://bjjzdx.tumblr.com
http://bjbdzbyz.tumblr.com
http://shbdzbyz.tumblr.com
http://pp1fe.tumblr.com
http://mo3ay.tumblr.com
http://p155f.tumblr.com
http://ff0xy.tumblr.com
http://l0q6c.tumblr.com
http://qnkso.tumblr.com
http://yubml.tumblr.com
http://ejubd.tumblr.com
http://cjb2t.tumblr.com
http://jgaey.tumblr.com
http://l89mp.tumblr.com
http://k1q63.tumblr.com
http://l2bwz.tumblr.com
http://u5zq9.tumblr.com
http://iq4an.tumblr.com
http://f2wla.tumblr.com
http://u40ng.tumblr.com
http://h4jfn.tumblr.com
http://u6cuu.tumblr.com
http://kztnc.tumblr.com
http://w9c84.tumblr.com
http://hpw9q.tumblr.com
http://hj4wp.tumblr.com
http://y9mok.tumblr.com
http://vev1n.tumblr.com
http://ev3db.tumblr.com
http://w7raj.tumblr.com
http://it5bt.tumblr.com
http://qjelk.tumblr.com
http://hyjlf.tumblr.com
http://bp4xn.tumblr.com
|
|