网络编程Socket之SocketOption参数

来源:互联网 发布:sql语言具有查询功能吗 编辑:程序博客网 时间:2024/06/02 16:45

SO_KEEPALIVE 

保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。
设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:
1、对方接收一切正常:以期望的ACK响应,2小时后,TCP将发出另一个探测分节。
2、对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。
3、对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。


SO_Backlog

TCP 缓存(TCP Backlog) 通常情况下,操作系统会使用一块限定的内存来处理 TCP 连接请求。每当用户端发送的 SYN 标志置位连接请求到服务端的一个合法端口(提供 TCP 服务的一端监听该端口)时,处 理所有连接请求的内存使用量必须进行限定。如果不进行限定,系统会因处理大量的 TCP 连接请求而耗尽内存,这在某种程度上可以说是一种简单的 DoS 攻击。这块经过限定的, 用于处理 TCP 连接的内存称为 TCP 缓存(TCP Backlog),它实际上是用于处理进站(inbound)

连接请求的一个队列。该队列保存那些处于半开放(half-open)状态的 TCP 连接项目,和已建 立完整连接但仍未由应用程序通过 accept()调用提取的项目。如果这个缓存队列被填满,除 非可以及时处理队列中的项目,否则任何其它新的 TCP 连接请求会被丢弃。 一般情况下,该缓存队列的容量很小。原因很简单,在正常的情况下 TCP 可以很好的处 理连接请求。 如果当缓存队列填满的时候新的客户端连接请求被丢弃, 客户端只需要简单的 重新发送连接请求,服务端有时间清空缓存队列以相应新的连接请求。 在现实环境中,不同操作系统支持 TCP 缓冲队列有所不同。
backlog 指定了内核为此套接口排队的最大连接 个数,对于给定在监听 套接口,内核要维护两个对列,未链接
队列和已连接队列,根据TCP三路握手过程 中三个分节来分隔这两个队列。服务器处于listen状态时收到客户端syn分节(connect)时在未完成队列 中创建一个新在条目,然后用三路握手的第二个分节几服务器在syn响应阴对客户端syn的ack,此条目用第三个分节到达前(客户端对服务器syn在ack) 一直保留在未完成连接 列队中如果三路握手完成,该将从未完成队列搬到已完成队列 尾部。当进程调用accept时,从已完成队列 中在头部取出一个条目给进程,当已完成队列为空时进程 将睡眠,直到有条目 在已完成连接列队中才唤醒。backlog 被规定为两二个队列总和在最大值,大多数实现 默认值为5,但在高并发web服务器中此值显然 不够,lighttpd中此值 达到128*8.需要风轻云淡此值更大一此在原因是未完成连接发队列 在长度可能因为客户端syn的到达及等待三路招手第三个分节在到达延时而增大。netty 默认100

SO_BROADCAST

此项是启动和禁用发送广播消息的处理能力,它仅用于数据报套接字和支持广播消息概念的网络上。默认情况为datagramSocket设置此选项


SO_RCVBUF  SO_SNDBUF

先明确一个概念:每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。进程调用send发送的数据的时候,最简单情况(也是一般情况),将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send返回之时,数据不一定会发送到对端去(和write写文件有点类似),send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。后续我会专门用一篇文章介绍read和send所关联的内核动作。每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。

接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 UDP:当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。
以上便是TCP可靠,UDP不可靠的实现。
这两个选项就是来设置TCP连接的两个buffer尺寸的


SO_REUSEADDR

允许一个程序在多个实例对同一个端口进行绑定。
如果你定义个SO_REUSEADDR,只定义一个套接字在一个端口上进行监听,如果服务器出现意外而导致没有将这个端口释放,那么服务器重新启动后,你还可以用这个端口,因为你已经规定可以重用了,如果你没定义的话,你就会得到提示,ADDR已在使用中。用在多播的时候,也经常使用SO_REUSEADDR,也是为了防止机器出现意外,导致端口没有释放,而使重启后的绑定失败~


SO_LINGER

此选项指定函数close对面向连接的协议如何操作(如TCP)。内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。

/注:大致意思就是说SO_LINGER选项用来设置当调用closesocket时是否马上关闭socket;

SO_LINGER选项用来改变此缺省设置。使用如下结构:

struct linger {

     int l_onoff; /* 0 = off, nozero = on */

     int l_linger; /* linger time */

};

具体的描述如下:
1、若设置了SO_LINGER(亦即linger结构中的l_onoff域设为非零),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv()调用将以WSAECONNRESET出错。

2、若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅”或“从容”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。

3、若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger结构的l_onoff域设为零),则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。


//未完成 。。。。。。。。。。。。。。。。。以后整理

0 0
原创粉丝点击