一个没正常处理tcp对端关闭的bug

最近使用自研的http client时发现一个问题,对端在发送响应数据之后立即调用close关闭了连接,我这没有调用到响应的回调,而是调用到了连接关闭的回调。对端延迟一会再关闭连接就没问题,用curl去访问也是正常的。经过排查是没有正确处理对端关闭导致的。

根据gnu文档以及其他搜索结果,如果没通过SO_LINGER选项改变close的默认行为,调用close关闭socket时,会关闭两个方向的数据流。读方向上,内核会将套接字设置为不可读,任何读操作都会返回异常;写方向上,内核会尝试将发送缓冲区的数据发送,之后发送FIN包结束连接,这个过程中,往套接字写入数据都会返回异常;若对端还发送数据过来,会返回一个RST报文。

epoll触发EPOLLIN事件时,表示对应的连接上有数据可以读出。tcp连接的远端主动关闭连接,也相当于可读事件,因为需要处理发送来的FIN包。

有问题的接收代码如下,问题在于recv返回0时,没有处理已经收到的数据就直接关闭socket。

cpp 复制代码
int tcp_event::handle_read()
{
	octets& read_buf = _ses->get_read_buf();
	int ret_bytes = 0;
	while(true)
	{
		if(read_buf.full())
		{
			_ses->onrecv();
		}
		int bytes_cnt = recv(_fd, read_buf.end(), read_buf.free_space(), 0);
		if(bytes_cnt == 0)
		{
			_ses->close(CLOSE_REASON_ONRECV);
			return -1;
		}
		else if(bytes_cnt != -1)
		{
			ret_bytes += bytes_cnt;
			read_buf.resize(read_buf.size() + bytes_cnt);
		}
		else
		{
			if(errno == EAGAIN || errno == EWOULDBLOCK) break;
			if(errno == EINTR) continue;
			_ses->close(CLOSE_REASON_ONRESET);
			return -1;
		}
	}
	_ses->onrecv();
	return ret_bytes;
}
相关推荐
SHENGWEI胜为2 分钟前
二层网络广播风暴如何排查?从交换机接口计数器到 STP 拓扑变化分析
网络
智慧光迅AINOPOL36 分钟前
园区全光网IP+POL架构怎么设计:组网拓扑与带宽演进
网络协议·tcp/ip·架构
艾芯微科技1 小时前
HR911130C|汉仁 HANRUN 集成变压器千兆 RJ45 网口参数、电路、PCB 布线、替代与采购避坑
网络·单片机·嵌入式硬件·集成测试·51单片机
日常筹谋记1 小时前
工业厂房 TPO 防水卷材:技术需求如何传导到配方层面?
运维·网络·html
TechWayfarer3 小时前
PHP漏洞被利用,怎么揪出攻击IP?
开发语言·python·tcp/ip·网络安全·php
玄芯散人4 小时前
【元婴·106】I2C总线:地址冲突、Clock Stretching、总线死锁怎么破
网络
YH_Analytics4 小时前
2026 年增亮膜(DBEF)行业市场格局深度解析
大数据·网络
dk_tjy5 小时前
迪康网络运维故障自愈的自动化闭环技术路径分析
运维·网络·自动化
万联WANFLOW6 小时前
让分散的设备像在同一张局域网里:企业组网技术解析
运维·网络·网络安全·智能路由器
QY_Research_7 小时前
全球智能交通系统物联网市场规模及CAGR14.2%深度分析
大数据·网络·人工智能·物联网·制造