socket选项
时间:2009-04-14 来源:ddvv
1、设置/获取socket选项
有两个函数,可以用来对socket进行设置或获取当前设置:
|
level指定了系统应该如何“解释”设置项,或这可以说是设置项的“级别”:socket或者是特定的协议。在ipv4的网络中,常用到的level是SOL_SOCKET、IPPROTO_IP和IPPROTO_TCP。
2、常用的socket选项
2.1 SOL_SOCKET级
·SO_ERROR
当一个socket发生错误的时候,将使用一个名为so_error的变量记录对应的错误代码,这又叫做pending error,so_error为0时表示没有错误发生。一般来说,有2种方式通知进程有socket错误发生:
1、进程阻塞在select中,有错误发生时,select将返回,并将发生错误的socket标记为可读写;
2、如果进程使用信号驱动的I/O,将会有一个SIGIO产生并发往对应进程;
此时,进程可以通过SO_ERROR取得具体的错误代码。getsockopt返回后,*optval指向的区域将存储错误代码,而so_error被设置为0。
当so_error不为0时,如果进程对socket进行read操作,若此时接收缓存中没有数据可读,则read返回-1,且errno设置为so_error,so_error置为0,否则将返回缓存中的数据而不是返回错误;如果进行write操作,将返回-1,errno置为so_error,so_error清0。
注意,这是一个只可以获取,不可以设置的选项。
·SO_KEEPALIVE
当这个设置被打开时,如果一个处于连接状态的TCP socket在一定时间(默认值一般为2小时)内没有数据传输,那么此socket将自动的发送一个“心跳包”检测连接是否正常。发送心跳包之后,有3中可能的结果:
1、主机收到远程主机的ACK包,此时代表连接还处于正常状态,系统过一定时间后会再发心跳包。这整个过程中使用此socket的进程没有任何反映;
2、主机收到远程主机的RST包,此时表示远程主机出了异常(如崩溃后重启),连接被重置了。这时本机的so_error被设置为ECONNRESET,且socket被关闭。
3、主机没有收到远程主机发送的任何数据包。这时有2种可能,一是发生丢包事件,二是远程主机不可达。本机会每隔一段时间(一般是75秒)重发心跳包,如果重发一定次数后(一般8次)依然没有相应,则so_error被设置为ETIMEOUT;如果重发期间收到“主机不可达”的ICMP包,则将so_error设置为EHOSTUNREACH。socket被关闭。
可以看到,只要发生了错误,socket就会被关闭,所以这个选项称之为“make dead”更为恰当。
使用这个选项的一般是服务器,因为它要处理很多客户端连接,如果某些客户端异常导致连接“断开”,则需要发现这些连接并关闭,以节省资源。
另外,心跳时间(一般2小时)影响的范围是整个系统,因此如果修改了内核代码相应的值(需重新编译内核),则会影响到系统中的所有socket。
一些服务器,如FTP,使用的是应用程序级的心跳,而非SO_KEEPALIVE。这种方式能够灵活的控制心跳时间和重发时间。
附:检测TCP连接各种状态的方法。
(...未完...)
·SO_LINGER
在对面向连接的socket调用close时,这个选项将影响close的处理方式。SO_LINGER的*optval指向的是linger结构体:
|
|
flags |= O_NONBLOCK; |
即先获取当前flag,然后在当前设置的基础上进行改动。如果直接使用O_NOBLOCK设置,则会将原来其他非O_NOBLOCK标志清空。