socket通讯收到rst指令问题

现象为客户端连接服务端,服务端日志返回写socket成功,但是客户端报错“read socket error”

把能调的超时时间都调大了,但是还是报错

抓包结果服务端:

抓包结果客户端:

分析原因:

1、可以看到客户端是发送完请求后,收到rst指令,导致连接断开
客户端添加日志打印errno
 

{
		while((num=read(nsockfd,&buf[iReadlen],len-iReadlen))<0){	
            HtLog (gsLogFile, HT_LOG_MODE_NORMAL, __FILE__,__LINE__, "read socket num[%d]", num);
			if (errno == EINTR) continue; 
			HtLog (gsLogFile, HT_LOG_MODE_ERROR, __FILE__,__LINE__, "read socket error");
            HtLog (gsLogFile, HT_LOG_MODE_NORMAL, __FILE__,__LINE__, "errno[%d]", errno);
			alarm(0);
			return -1;
		}
		if(num == 0){
			alarm(0);
			return 0;
		}
		HtLog (gsLogFile, HT_LOG_MODE_NORMAL, __FILE__,__LINE__, "num[%d]", num); /*[*1*] modify ERROR -> NORMAL*/
		iReadlen+=num;
		if(iReadlen>=len) break;
		if( vnRdFlg ) break;
	}

结果为104:

errno: 104      Connection reset by peer

2、经过排查代码

int Setsokopt(int sdNew)
{
	struct linger soLinger;
	int soKeepAlive,soReuseAddr;

   	/*************************************************/
	/* Set socket options for new socket              */
	/*************************************************/
	soLinger.l_onoff = 1;
	soLinger.l_linger = 0;
	if( -1 == setsockopt(sdNew,
		             SOL_SOCKET,
		             SO_LINGER,
		             (char*)&soLinger,
		             sizeof(soLinger)))
	{
		HtLog (gsLogFile, HT_LOG_MODE_ERROR, __FILE__,__LINE__,
			 "set linger option failed!");
		return -1;
	}

	soKeepAlive = 0;
	if( -1 == setsockopt(sdNew,
		             SOL_SOCKET,
		             SO_KEEPALIVE,
		             &soKeepAlive,
		             (int)sizeof(soKeepAlive)))
	{
		HtLog (gsLogFile, HT_LOG_MODE_ERROR, __FILE__,__LINE__,
			"set keepalive option failed!");
		return -1;
	}

	soReuseAddr = 1;
	if( -1 == setsockopt(sdNew,
		             SOL_SOCKET,
		             SO_REUSEADDR,
		             &soReuseAddr,
		             (int)sizeof(soReuseAddr)))
	{
		HtLog (gsLogFile, HT_LOG_MODE_ERROR, __FILE__,__LINE__,
			"set reuse addr option failed!");
		return -1;
	}
	return 0;
}

代码中设置了linger,并且soLinger.l_linger = 0;
3、查询得知“在设置SO_LINGER选项时,指定等待时间为0,此时调用主动关闭时不会发送FIN来结束连接,而是直接将连接设置为CLOSE状态,清除套接字中的发送和接收缓冲区,直接对对端发送RST包。”
4、将l_linger改为1就可以了
5、正常TCP握手是返回FIN,但是由于设置了soLinger,返回了RST。和网络延迟有关系,就是说服务端发了两个包,一个是数据包,一个是RST包,但是客户端总是先收到RST包导致接收数据失败
6、参考资料:
https://www.cnblogs.com/jingzhishen/p/5543627.html
https://www.cnblogs.com/Jimmy1988/p/7485133.html
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值