server后台TCP连接存活问题
公司的server后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了server后台在执行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统。存在较多的TCP连接。
1. 问题分析
首先在公司内部測试server上部署,使用LoadRunner做压力測试,能正常执行,然后那边的同事反馈该地方信号较差。考虑到接入的问题。有可能接入进程的FD资源耗尽,导致accept失败。推论的根据是对于TCP连接来说,假设client那边因为一些异常情况导致断网而未能向server发起FIN关闭消息,服务端这边若没有设置存活检測的话。该连接会存在(存活时间暂未測)。
2. 实验測试
这里简单地写了一个服务端的程序。主要功能是回应,即接受一个报文(格式:2Byte报文长度+报文内容),然后原封不动将报文内容发回client。

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 }

測试内容:
注:clientIP: 192.168.10.108 serverIP&Port: 192.168.10.110:7777
a. client发送一个报文至服务端,然后断网。
(这里对程序做了点修改。这次实验凝视了write响应,防止write影响測试,后面一个实验会使用write)。
server后台TCP连接存活问题的更多相关文章
- 服务器后台TCP连接存活问题
0. 背景 公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接 ...
- ESP8266 station模式下建立client、server TCP连接
程序实现内容: 1.在station模式下,ESP8266作为client.server进行TCP连接2.实现数据的发送.接收(同时回传)实现思路:TCP网络通信分层为:应用层.网络层.数据链路层.物 ...
- TCP连接状态详解及TIME_WAIT过多的解决方法
上图对排除和定位网络或系统故障时大有帮助,但是怎样牢牢地将这张图刻在脑中呢?那么你就一定要对这张图的每一个状态,及转换的过程有深刻地认识,不能只停留在一知半解之中.下面对这张图的11种状态详细解释一下 ...
- close_wait状态和time_wait状态(TCP连接)
1.CLOSE_WAIT的简单解决方案 不久前,我的Socket Client程序遇到了一个非常尴尬的错误.它本来应该在一个socket长连接上持续不断地向服务器发送数据,如果socket连接断开,那 ...
- 高并发TCP连接数目问题
linux可通过五元组唯一确定一个链接:源IP,源端口,目的IP,目的端口,传输层协议.而一个端口不允许被两个及以上进程占用(一个进程可同时占用多个端口),据此是否可以推测一台linux服务器最多可以 ...
- TCP连接的状态与关闭方式及其对Server与Client的影响
TCP连接的状态与关闭方式及其对Server与Client的影响 1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用. ...
- TCP连接的状态与关闭方式,及其对Server与Client的影响
1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用.特定数据包以及超时等,具体状态如下所示: CLOSED:初始状态, ...
- TCP连接——爱的传声筒
TCP连接——爱的传声筒 TCP通信最重要的特征是:有序(ordering)和可靠(reliable).有序是通过将文本流分段并编号实现的.可靠是通过ACK回复和重复发送(retransmission ...
- TCP连接与关闭
1.建立连接协议(三次握手) (1)客户端发送一个带SYN标志的TCP报文到服务器.这是三次握手过程中的报文1. (2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和S ...
随机推荐
- POJ 3177 Redundant Paths (边双连通+缩点)
<题目链接> <转载于 >>> > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...
- Django的MVT模型
MVC模型和MVT模型 MVC简介: MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在2 ...
- Ef 自动迁移,日志
Ef 迁移 在vs打开程序控制台 2,选择程序集 ,如果是初次,输入 Enable-Migrations,启动迁徙 3 添加迁移,完成修改 4,之后会自动生成迁移配置文件. 然后再上下文类中加入 两 ...
- c#一步一步实现ORM
本篇适合新手了解学习orm.欢迎指正,交流学习. 现有的优秀的orm有很多. EF:特点是高度自动化,缺点是有点重. Nhibnate:缺点是要写很多的配置. drapper:最快的orm.但是自动化 ...
- 在Eclipse中使用Junit进行单元测试
单元测试与Junit4 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离 ...
- C++多态实现原理详解
C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数.如果对象类型是派生类,就调用派生类的函数:如果对象类型是基类 ...
- BZOJ.5093.[Lydsy1711月赛]图的价值(NTT 斯特林数)
题目链接 对于单独一个点,我们枚举它的度数(有多少条边)来计算它的贡献:\[\sum_{i=0}^{n-1}i^kC_{n-1}^i2^{\frac{(n-2)(n-1)}{2}}\] 每个点是一样的 ...
- 【转】Linux服务部署--Java(三) Nginx
原文地址:Nginx Linux详细安装部署教程 一.Nginx简介 Nginx是一个web服务器也可以用来做负载均衡及反向代理使用,目前使用最多的就是负载均衡,具体简介我就不介绍了百度一下有很多,下 ...
- 【DWM1000】 code 解密1一 去掉Main 函数多余内容
蓝点DWM1000 模块已经打样测试完毕,有兴趣的可以申请购买了,更多信息参见 蓝点论坛 正文: 室内定位兴起,DWM1000 作为超宽带UWB的代表,在国内用的越来越多,但是可见资料非常少. 一方面 ...
- Oracle内置函数
单行函数:当查询表或试图时每行都能返回一个结果,可用于select,where,order by等子句中. 对于没有目标的select查询用dual表,这个表时真实存在的,每个用户都可以读取. 单行函 ...