关键词:
公司的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 "); 27 exit(-1); 28 } 29 30 if ( listen( nServerFd, 128 ) < 0 ) 31 { 32 printf("listen error "); 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 "); 73 74 if ( (nRead = read( nClientFd, buf, 2 )) != 2 ) 75 { 76 printf("Read Data Len error "); 77 pthread_exit(NULL); 78 } 79 80 nDataLen = *(unsigned short *)buf; 81 printf("nDataLen [%d] ", nDataLen); 82 nDataLen = buf[0]*256 + buf[1]; 83 printf("nDataLen [%d] ", 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 "); 93 pthread_exit( NULL ); 94 } 95 nTotal += nRead; 96 if ( nTotal >= nDataLen ) 97 { 98 break; 99 } 100 } 101 printf("nTotal [%d] ", nTotal); 102 103 sleep(5); 104 105 int nWrite = write( nClientFd, buf, nTotal ); 106 printf("nWrite[%d] ", nWrite); 107 108 printf("Not Write ResetOneShot [%d] ", 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 "); 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 "); 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 "); 167 close( events[i].data.fd ); 168 }else 169 { 170 printf("Some thing happened "); 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.com/Db_name、端口 1433 的 TCP/IP 连接失败
】与主机server.com/Db_name、端口1433的TCP/IP连接失败【英文标题】:TheTCP/IPconnectiontohostserver.com/Db_name,port1433hasfailed【发布时间】:2013-03-0807:45:25【问题描述】:这个问题可能是一个基本问题,如果是,请原谅我。我正在尝试将我的A... 查看详情
tcp连接时,brokenpipe错误的原因以及解决方法
问题:写了一个server和一个client,UNIX套接字的,server不断接收消息并打印出来,client是一个交互程序,输入一个消息回车发送,接着又可以输入消息。出问题了:当server监听着,client第一次发送消息成功,server接收并打印出来... 查看详情
tcp长连接和短连接
tcp长连接和短连接TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次握手,所以说每个连接的建... 查看详情
C# Async TCP Server 矫枉过正?
】C#AsyncTCPServer矫枉过正?【英文标题】:C#AsyncTCPServeroverkill?【发布时间】:2011-01-2721:36:19【问题描述】:这确实是一个实施问题,所以我觉得最好从我的具体案例开始。我有一个C#服务器,它从移动客户端异步侦听TCP连接。当... 查看详情
tcp连接性能指标之tcp关闭过程(四次挥手)
...程(四次挥手):ESTABLISHED:当前建立连接状态CLOSE_WAIT:Server端收到来自Client端的FIN包后,发送ACK回Client端,进入CLOSE_WAIT状态。LAST_ACK:同时Server端向上层应用告知客户端关闭消息,发送FIN包回Client端,然后进入LAST_ACK阶段,等待... 查看详情
tcp的长连接与短连接
...接当网络通信时采用TCP协议时,在真正的读写操作之前,server(服务器)与client(客户端)之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则... 查看详情
什么是tcp长连接和短连接。谢谢
什么是tcp长连接和短连接。谢谢 1、client向server发起连接请求,server接到请求,然后双方建立连接。client向server发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作,不过一般都是client... 查看详情
tcp粘包
...单概念长连接与短连接:1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开,然后再进行报文发送和接收。2.短连接 Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立... 查看详情
44tcp协议详解
...志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一... 查看详情
使用 libevent 广播 TCP-Server
】使用libevent广播TCP-Server【英文标题】:BroadcastTCP-Serverwithlibevent【发布时间】:2011-06-2918:39:52【问题描述】:我正在寻找一些简单的基于libevent的TCP-Server的示例代码,它将传入消息广播到所有连接的客户端。在网上我只找到了... 查看详情
tcp连接建立与释放
...dquo;的过程。过程如下client发送SYN包(值为j)以及SEQ包到server端,此时client进入SYN_SEND状态。此为第一次握手。server端收到SYN包后,发送一个ACK(值为seq+1)确认包和SYN(值为k)给client,此时server进入SYN_RECV状态。此为第二次握... 查看详情
iOS 应用程序如何在后台无限期地保持 TCP 连接处于活动状态?
】iOS应用程序如何在后台无限期地保持TCP连接处于活动状态?【英文标题】:HowcananiOSappkeepaTCPconnectionaliveindefinitelywhileinthebackground?【发布时间】:2011-08-1523:17:49【问题描述】:一个iPhone应用程序,通过TCP连接到远程服务器。使... 查看详情
TCP 连接中的“积压”是啥?
...个python程序,它充当服务器侦听对端口9999的连接请求:#server.pyimportsocketimporttime#createasocketobjectserversocket=sock 查看详情
当 iOS 应用程序确实进入后台时,TCP 和 UDP(使用多播)连接会发生啥情况
】当iOS应用程序确实进入后台时,TCP和UDP(使用多播)连接会发生啥情况【英文标题】:WhathappenstoTCPandUDP(withmulticast)connectionwhenaniOSApplicationdidenterbackground当iOS应用程序确实进入后台时,TCP和UDP(使用多播)连接会发生什么情况... 查看详情
tcp/ipkeepalive
...的keepalivekeepalive是设置在操作系统级别,作用于到本机的连接。在一定时间内对远程主机发送TCP探测报文用于探测对方是否存活。 上图2个场景是最常见的,但是针对于keepalive的问题是一样的。无非就是客户端和最终的WEB服... 查看详情
ios即时通讯(二):心跳保活
...是TCP协议,应用层的心跳保活仍旧必不可少。在使用TCP长连接的IM服务设计中,往往都会涉及到心跳。心跳一般是指客户端每隔一定时间向服务端发送自定义指令,以判断双方是否存活,因其按照一定间隔发送,类似于心跳,故... 查看详情
(经典)tcp粘包分析
...单概念长连接与短连接:1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开,然后再进行报文发送和接收。2.短连接 Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立... 查看详情
tcp及socket
...说的就是TCP建立连接的过程。具体的步骤如下:第一步:Server监听端口,状态为:Listen 第二部:Client发送SNY包,请求连接,并将状态改为:SYN_SEND第三部:Server发送ACK包,和SNY包,同意,并请求连接,状态改为:SYN_RCVD第四... 查看详情