服务器后台TCP连接存活问题
0. 背景
公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接。
1. 问题分析
首先在公司内部测试服务器上部署,使用LoadRunner做压力测试,能正常运行,然后那边的同事反馈该地方信号较差。考虑到接入的问题,有可能接入进程的FD资源耗尽,导致accept失败。推论的依据是对于TCP连接来说,如果客户端那边由于一些异常情况导致断网而未能向服务器发起FIN关闭消息,服务端这边若没有设置存活检测的话,该连接会存在(存活时间暂未测)。
2. 实验测试
这里简单地写了一个服务端的程序,主要功能是回应,即接受一个报文(格式:2Byte报文长度+报文内容),然后原封不动将报文内容发回客户端。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h> int g_epfd; int InitServer( unsigned short port )
{
int nServerFd = socket( AF_INET, SOCK_STREAM, ); struct sockaddr_in addr;
memset( &addr, , sizeof(addr) ); addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = ; if ( bind( nServerFd, (struct sockaddr *)&addr, sizeof(addr) ) < )
{
printf("bind error\n");
exit(-);
} if ( listen( nServerFd, ) < )
{
printf("listen error\n");
exit(-);
} return nServerFd;
} int AddFd( int epfd, int nFd , int nOneShot)
{
struct epoll_event event;
memset( &event, , sizeof( event) ); event.data.fd = nFd;
event.events |= EPOLLIN | EPOLLRDHUP | EPOLLET; if ( nOneShot ) event.events |= EPOLLONESHOT; return epoll_ctl( epfd, EPOLL_CTL_ADD, nFd, &event );
} int ResetOneShot( int epfd, int nFd )
{
struct epoll_event event;
memset( &event, , sizeof(event) ); event.data.fd = nFd;
event.events |= EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; return epoll_ctl( epfd, EPOLL_CTL_MOD, nFd, &event);
} void * ReadFromClient( void * arg )
{
int nClientFd = (int)arg;
unsigned char buf[];
const int nBufSize = sizeof( buf );
int nRead;
int nTotal;
int nDataLen; printf("ReadFromClient Enter\n"); if ( (nRead = read( nClientFd, buf, )) != )
{
printf("Read Data Len error\n");
pthread_exit(NULL);
} nDataLen = *(unsigned short *)buf;
printf("nDataLen [%d]\n", nDataLen);
nDataLen = buf[]* + buf[];
printf("nDataLen [%d]\n", nDataLen); nRead = ;
nTotal = ;
while( )
{
nRead = read( nClientFd, buf + nRead, nBufSize );
if ( nRead < )
{
printf("Read Data error\n");
pthread_exit( NULL );
}
nTotal += nRead;
if ( nTotal >= nDataLen )
{
break;
}
}
printf("nTotal [%d]\n", nTotal); sleep(); int nWrite = write( nClientFd, buf, nTotal );
printf("nWrite[%d]\n", nWrite); printf("Not Write ResetOneShot [%d]\n", ResetOneShot(g_epfd, nClientFd)); return NULL;
} int main(int argc, char const *argv[])
{
int i;
int nClientFd;
pthread_t tid;
struct epoll_event events[]; int nServerFd = InitServer( );
if ( nServerFd < )
{
perror( "nServerFd" );
exit(-);
} int epfd = epoll_create( ); g_epfd = epfd; int nReadyNums; if ( AddFd( epfd, nServerFd, ) < )
{
printf("AddFd error\n");
exit(-);
} while( )
{
nReadyNums = epoll_wait( epfd, events, , -1 ); if ( nReadyNums < )
{
printf("epoll_wait error\n");
exit(-);
} for ( i = ; i < nReadyNums; ++i)
{
if ( events[i].data.fd == nServerFd )
{
nClientFd = accept( nServerFd, NULL, NULL ); AddFd( epfd, nClientFd, ); }else if ( events[i].events & EPOLLIN )
{
// Can be implemented by threadpool
//Read data from client
pthread_create( &tid, NULL, ReadFromClient, (void *)(events[i].data.fd) ); }else if ( events[i].events & EPOLLRDHUP )
{
//Close By Peer
printf("Close By Peer\n");
close( events[i].data.fd );
}else
{
printf("Some thing happened\n");
} }
} return ;
}
测试内容:
注:客户端IP: 192.168.10.108 服务器IP&Port: 192.168.10.110:7777
a. 客户端发送一个报文至服务端,然后断网。(这里对程序做了点改动,这次实验注释了write响应,防止write影响测试,后面一个实验会使用write)。
客户端断网后,使用netstat查看网络连接状态发送客户端与服务端还处于established状态,如图所示。

a. 实验结果
服务端没有检测到客户端断网,依然处于连接状态。
b. 客户端发送一个报文至服务端,然后断网,关闭客户端,再重复一次。
这次试验测试重新联网,程序再次建立Socket连接是否会导致之前的连接被检测到。

b. 实验结论:
重新联网,程序再次建立Socket连接之前的连接不会被检测到。
c. 客户端发送一个报文至服务端,然后断网。(这次实验使用了write响应,查看write后的结果)。
这里查看到Write居然成功了,成功了....。

c. 实验结论:
这次使用write不会检测对端是否已经断了。
3. 解决方案
临时:使用TCP的选项SO_KEEPALIVE检测客户端是否已异常掉了(setsockopt)。
后续改进:使用心跳包来检测长连接存活问题。
注:SO_KEEPALIVE明天再补充,回家了,只有一台笔记本直接装了Ubuntu,没装虚拟机,伤不起。
4. 补充
如果什么不对的或者建议直接说,多讨论讨论比较好。
服务器后台TCP连接存活问题的更多相关文章
- server后台TCP连接存活问题
公司的server后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了server后台在执行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统.存在较多的TCP连接 ...
- 单台服务器最大tcp连接
如果对服务器进行压力测试,常常出现这种情况 tcp连接数过多 netstat -an windows查看tcp连接数 那么怎么增加单台服务器的最大连接数呢? 最简单的办法,增加内 ...
- 【故障公告】推荐系统中转站撑爆服务器 TCP 连接引发的故障
上周五下午,我们在博客中部署了推荐系统,在博文下方显示“最新IT新闻”的地方显示自动推荐的关联博文.我们用的推荐系统是第四范式的推荐服务,我们自己只是搭建了一个推荐系统中转站(基于 ASP.NET C ...
- TCP 连接
面试题传送 TCP 报文格式 此处介绍建立或者断开TCP连接时,需要了解的TCP报文段首部字段含义: 序列号 seq:占4个字节(32位),用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上 ...
- 简述TCP连接的建立与释放(三次握手、四次挥手)
在介绍TCP连接的建立与释放之前,先回顾一下相关知识. TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,H ...
- TCP连接中time_wait在开发中的影响-搜人以鱼不如授之以渔
根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),T ...
- TCP连接的建立与释放(三次握手与四次挥手)
TCP连接的建立与释放(三次握手与四次挥手) TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,HTTP协议 ...
- 网络学习笔记(一):TCP连接的建立与关闭
五层网络模型分为:物理层.数据链路层.网络层.传输层.应用层.其中,传输层有两种主要协议:面向连接的TCP(Transmission Control Protocol 传输控制协议).无连接的UD ...
- TCP连接与释放
TCP连接的建立 三次握手 TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态. TCP客户进程也是先创建传输控制块TCB,然后向服务器 ...
随机推荐
- iOS开发,系统自带的分享简单实现
由于simulator设置里面没有新浪微博的选项,所以选择了真机调试,成功了.代码不多,包含头文件 没有配置登录信息的话,是没有作用的 ...
- 神经网络dropout
训练集上面,加一个bool型的开关 做预测的时候,不需要打开开关,而是所有的数乘以p, 实际工业界做的时候是: 在训练的时候都除以p,在做预测的时候什么时候都不用干
- 数据库开发基础-SQl Server 链接查询
连接查询:通过连接运算符可以实现多个表查询.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 常用的两个链接运算符: 1.join on 2.union 在关 ...
- 「c++小学期」实验题目及代码
面向对象编程的C++,和平时做题用的C++还是有差距的.实验的题目都是小题目,就都做一下吧.(没放代码的为要验收的 实验一 简单C++程序设计 1. 猜价格游戏 编写C++程序完成以下功能: (1) ...
- K-means之matlab实现
引入 作为练手,不妨用matlab实现K-means 要解决的问题:n个D维数据进行聚类(无监督),找到合适的簇心. 这里仅考虑最简单的情况,数据维度D=2,预先知道簇心数目K(K=4) 理论步骤 关 ...
- bzoj2765[JLOI2010]铁人双项比赛
题意:铁人双项比赛由长跑和骑自行车组成,参赛选手必须先完成k公里的长跑,然后完成r公里的骑车,才能到达终点.参赛选手有的擅长长跑,有的擅长骑车. 如果总赛程s=k+r一定,那么K越大,对擅长长跑的选手 ...
- ecshop /goods.php SQL Injection Vul
catalogue . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述2. 漏洞触发条件 0x1: poc http://localhost ...
- ExceptionLess新玩法 — 记日志
ExceptionLess 之前也有介绍过这个框架,其实网上也有很多的资料,无论是部署还是一些详细的高级玩法都讲的很清楚也很棒,博主也学习了一些他们的博文,因为很多的东西比如本地部署别人已经写了,我再 ...
- JSP实现数据传递与保存
业务逻辑: 1.登陆login.jsp 2.判断登陆是否成功check.jsp 3.登陆成功页面newsDetail.jsp 4.登陆失败转发到login.jsp 代码如下: <%@ page ...
- 个人作业—Week2:微软必应词典案例分析
调研.评测 bug报告: 标题:Window 10版必应词典客户端口语练习功能无法使用 环境:Window 10, 微软必应词典(UWP) 版本2.6.1.0,屏幕无重力感应模块 重现步骤: 1) ...