Advanced Sockets Programming 2 学时
Socket Options 了解套接口选项是很重要的,虽然我们不知道什么时候会用到它 详细的内容在书上有描述,我们只是简要介绍它能做什么
Socket Options 不同的属性可以用来决定套接口的行为 通过设置属性来告诉操作系统/协议栈我们需要的行为 包含通用的选项(对所以套接口都有效)以及协议相关的选项
Option types 许多套接口选项是布尔型的,用于启用或禁止套接口的某个属性(1-启用,0-禁止) 其它的选项都是比较复杂的类型,包括int, timeval, in_addr, sockaddr, 等等,设置特定的值
#include <winsock2.h> 设置和获取选项的值 getsockopt() 读取一个套接口选项的当前值 setsockopt() 设置一个套接口选项的值 #include <winsock2.h>
getsockopt() level 指明了该选项是一个通用选项还是一个协议相关选项 (哪一个级别的代码应该来解释该选项). int getsockopt( SOCKET s, int level, int optname, char *optval, int *optlen); level 指明了该选项是一个通用选项还是一个协议相关选项 (哪一个级别的代码应该来解释该选项).
setsockopt() int setsockopt( SOCKET s, int level, int optname, char *opval, int optlen);
通用选项SOL_SOCKET 协议无关的选项. 由套接口的系统代码来处理 某些通用选项只是特定类型的套接口支持 (SOCK_DGRAM, SOCK_STREAM).
一些通用的选项 SO_BROADCAST SO_KEEPALIVE SO_LINGER SO_RCVBUF,SO_SNDBUF SO_RCVTIMEO,SO_SNDTIMEO SO_REUSEADDR
SO_BROADCAST 布尔型选项:启用或禁止广播消息的发送 下面的数据链路层必须支持广播! 只对SOCK_DGRAM套接口有用 防止应用不小心发送广播(当指定了广播地址时,OS会查询该选项) 【architecture principles of the Internet】
SO_KEEPALIVE 布尔型选项: 周期性的测试连接是否存活 激活意味着,如果很长一段时间没有数据流时, STREAM套接口应发送一个探测消息给对端 由TCP使用——允许一个进程来检测对端进程/主机是否已经崩溃了 通常由应用层通过TCP的紧急数据机制来检查对端以及连接的存活
Out-of-Band Data TCP 提供了一种机制,使高优先级数据的传递放在普通数据的前面 我们基本上可以认为这里有两个流: normal data TCP PORT A TCP PORT B special data
send(sd,buff,1,MSG_OOB); Sending OOB Data send(sd,buff,1,MSG_OOB); Use send() to put a single byte of urgent data in a TCP stream. The TCP layer adds some segment header info to let the other end know there is some OOB data.
TCP OOB Data TCP supports something like OOB data using URGENT MODE (a bit is set in a TCP segment header). A TCP segment header field contains an indication of the location of the urgent data in the stream (the byte number).
Receiving OOB Data select() will tell you an exception condition is present. the data can be read using recv() with a MSG_OOB flag set.
So what? OOB Data might be used: a heartbeat between the client and server to detect early failure (example in the book). A way to communicate an exceptional condition to a peer even when flow control has stopped the sender.
SO_LINGER Value is of type: 用来控制调用closesocket()是否需要等待数据的确认、等待多久 struct linger { u_short l_onoff; /* 0 = off */ u_short l_linger; /* time in seconds */ }; 用来控制调用closesocket()是否需要等待数据的确认、等待多久 只有面向连接的套接口有效
SO_LINGER用处 默认情况下,在TCP套接口上调用closesocket()会立即返回 关闭进程没有办法知道对端是否收到了数据 设置SO_LINGER意味着关闭进程可以判定对端机器已经收到了数据(但不能判定这些数据是否被读取了read())
shutdown() vs SO_LINGER 课本没有介绍shutdown()的使用,但大家可以查一下MSDN SO_LINGER只能确保自己的数据被对方收到了,不能保证对方的数据被自己完全接收了(不知道对方何时发完)
SO_RCVBUF SO_SNDBUF 整形选项 – 改变发送和接收的缓冲大小 可以用在STREAM和DGRAM的套接口上 对于TCP,该选项影响流量控制中的窗口大小——连接建立前必须设置完毕(在TCP的确认中通知接收窗口的大小)
SO_RCVTIMEO SO_SNDTIMEO Timeval型选项 – 设置发送和接收的超时长短 阻塞模式下调用发送/接收函数时,如果在SO_RCVTIMEO/SO_SNDTIMEO 时间内接收和发送还未成功,函数也会返回并得到一个错误
SO_REUSEADDR 布尔型选项:允许套接口绑定到一个已在使用的地址上 默认情况是不能这样绑定的 主要是服务器编程时使用:服务器进程(应用)重启时,可能监听端口 尚未完全关闭(处于TIME_WAIT状态P68),这时绑定回原来的端口就会出错
SO_REUSEADDR 可以用来为相同的服务在不同的接口(或同一个接口上的不同IP地址)上建立服务器 虚拟Web服务器可以工作在这种模式
IP层选项IPPROTO_IP IP_HDRINCL: 在原始IP套接口上使用,可以自己构造IP头部 IP_ADD_MEMBERSHIP IP_DROP_MEMBERSHIP IP_MULTICAST_IF IP_MULTICAST_LOOP IP_MULTICAST_TTL
Broadcast & Multicast example
原始套接口 提供读写IP/ICMP/IGMP以及构造特殊的IP报文的功能 SOCKET sock = socket(AF_INET, SOCK_RAW, protocol);