socket的常见问题---《六》

1) 在线程中碰到socket阻塞怎么办?

比如socket服务器accept阻塞了,造成线程不能顺利退出?

解决办法通过socket的KeepAlive机制;

 

 

 

2) 如何检测socket连接是否断开或异常?

1)通过心跳机制;

       2)KeepAlive机制;

 

3)Socket 常用的属性

SO_REUSEADDR:

1、 当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 

2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。 
3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。 
4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

SO_RECVBUF/SO_SNDBUF

设置socket的接收和发送缓冲;

 

SO_RCVTIMEO/ SO_SNDTIMEO

设置socket的发送超时和接收超时,在阻塞socket中非常有用,避免一直阻塞;

 

SO_LINGER:

linger,顾名思义是延迟延缓的意思,这里是延缓面向连接的socket的close操作。默认,close立即返回,但是当发送缓冲区中还有一部分数据的时候,系统将会尝试将数据发送给对端。SO_LINGER可以改变close的行为。避免socket进入TIME_WAIT状态;

 

SO_KEEPALIVE

SO_KEEPALIVE/TCP_KEEPCNT/TCP_KEEPIDLE/TCP_KEEPINTVL
如果一方已经关闭或异常终止连接,而另一方却不知道,我们将这样的TCP连接称为半打开的。TCP通过保活定时器(KeepAlive)来检测半打开连接。
在高并发的网络服务器中,经常会出现漏掉socket的情况,对应的结果有一种情况就是出现大量的CLOSE_WAIT状态的连接。这个时候,可以通过设置KEEPALIVE选项来解决这个问题,当然还有其他的方法可以解决这个问题。

 

 

TCP_DEFER_ACCEPT

defer accept,从字面上理解是推迟accept,实际上是当接收到第一个数据之后,才会创建连接。对于像HTTP等非交互式的服务器,这个很有意义,可以用来防御空连接攻击(只是建立连接,但是不发送任何数据)。
使用方法如下:
val = 5;
setsockopt(srv_socket->fd, SOL_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val));
里面 val 的单位是秒,注意如果打开这个功能,kernel val 秒之内还没有收到数据,不会继续唤醒进程,而是直接丢弃连接。如果服务器设置TCP_DEFER_ACCEPT选项后,服务器受到一个CONNECT请求后,三次握手之后,新的socket状态依然为SYN_RECV,而不是ESTABLISHED,操作系统不会Accept
由于设TCP_DEFER_ACCEPT选项之后,三次握手后状态没有达到ESTABLISHED而是SYN_RECV。这个时候,如果客户端一直没有发送"数据"报文,服务器将重传SYN/ACK报文,重传次数受net.ipv4.tcp_synack_retries参数控制,达到重传次数之后,才会再次进行setsockopt中设置的超时值,因此会出现SYN_RECV生存时间比设置值大一些的情况。

TCP_NODELAY/TCP_CHORK

CP_NODELAYTCP_CORK基本上控制了包的“NagleNagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。TCP_NODELAYTCP_CORK都禁掉了Nagle算法,只不过他们的行为不同而已。
TCP_NODELAY
不使用Nagle算法,不会将小包进行拼接成大包再进行发送,直接将小包发送出去,会使得小包时候用户体验非常好。
当在传送大量数据的时候,为了提高TCP发送效率,可以设置TCP_CORKCORK顾名思义,就是"塞子"的意思,它会尽量在每次发送最大的数据量。当设置了TCP_CORK后,会有阻塞200ms,当阻塞时间过后,数据就会自动传送。

 

 

4) socket 连接状态

 

CLOSED:无连接是活动的或正在进行;
LISTEN:服务器在等待进入呼叫;
SYN_RECV:一个连接请求已经到达,等待确认;
SYN_SENT:应用已经开始,打开一个连接;
ESTABLISHED:正常数据传输状态;
FIN_WAIT1:应用说它已经完成;
FIN_WAIT2:另一边已同意释放;
ITMED_WAIT:等待所有分组死掉;
CLOSING:两边同时尝试关闭;
TIME_WAIT:另一边已初始化一个释放;
LAST_ACK:等待所有分组死掉;

 

你可能感兴趣的:(socket的常见问题---《六》)