socket编程

本文详细探讨了TCP连接关闭的步骤,包括TIME_WAIT和FIN_WAIT状态,以及如何通过设置linger选项来避免资源耗尽。同时,解释了服务器重启时Address already in use的问题,提出了解决方案,包括设置socket可重用和非阻塞模式。此外,还介绍了socket编程中的相关函数和技巧,如设置缓冲区大小、非阻塞模式等。
摘要由CSDN通过智能技术生成

13. sockaddr_in清空方式

初始化可直接清空

sockaddr_in addr = {0};


1.TIME_WAITFIN_WAIT

问题:一方close(fd1),另一方没有close(fd2),导致调用方fd1处于TIME_WAIT和FIN_WAIT,socket不能使用。

解决方法:struct linger ling = {1,0} 跳过四步握手,直接强杀socket,socket直接CLOSED呈可用状态。


tcp连接的关闭经过FIN->ACK->FIN->ACK四步握手。

服务器先调用close(socket):


客户端先调用close(socket):


过程:

        1.A调用close(socket)发送FIN表示A的数据传输完成、没有其他数据要传输给B

        2.B发ACK对FIN进行应答

        3.A进入FIN_WAIT_2、B进入CLOSE_WAIT

        4.此时B仍旧可以发送数据给A(A的事儿处理完了不代表B的事儿也处理完了)

        5.B把其余数据发送给A完成传输

        6.B调用close(socket)发FIN

        7.A发ACK予以响应

        8.连接关闭


一个close()对应着一个FIN,一个FIN对应着一个close()调用。只有双方都使用close关闭socket后,连接才算关闭,以上就是以绅士的方式关闭TCP连接。但是不管是谁,率先调用close()的一方必回最终处于TIME_WAIT状态,在一段时间后方可变为CLOSED状态,此状态下的socket表可用。


在某些情况下,比如由服务器主动关闭连接的情况,如果client足够好调用了close(),则服务器端会有大量socket处于TIME_WAIT状态。如果client非善类,不曾调用close(),则服务器会有大量socket处于FIN_WAIT2状态下。这两种情况最终将会导致资源耗尽。


CentOS6.4 系统下为了解决这一问题,先后试着更改系统文件,close()前先调用shutdown()强制关闭,均不起作用。


最终解决办法如下:

server每接受一个新连接,即对生成的socket进行参数设置:

struct linger ling = {1,0};
if(setsockopt(fd,SOL_SOCKET,SO_LINGER,(void*)&ling,sizeof(ling)) !=0){
	std::cout<<"set socket fail"<<std::endl;
	return;
}
SO_LINGER显示需设置的选项,struct linger结构:

struct linger {
int l_onoff;   //0即关闭此选项,1即打开此选项
int l_linger;  //逗留时间	
};

有下列三种情况:

a、设置 l_onoff0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据;

 

b、设置 l_onoff为非0l_linger0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT和FIN_WAIT2状态;

 

c、设置 l_onoff 为非0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值