Option Type
-----------------------------------------------------
SO_BROADCAST BOOL
SO_DEBUG BOOL
SO_DONTLINGER BOOL
SO_DONTROUTE BOOL
SO_KEEPALIVE BOOL
SO_LINGER struct linger FAR*
SO_OOBINLINE BOOL
SO_RCVBUF int
SO_REUSEADDR BOOL
SO_SNDBUF int
TCP_NODELAY BOOL
(1)SO_BROADCAST -- 适用於 UDP socket。其意义是允许 UDP socket 「广播」(broadcast)讯息到网路上。
(2)SO_DONTLINGER -- 适用於 TCP socket。其意义是让 socket 在呼叫closesocket() 关闭时,能马上 return,而不用等到资料都送完後才从函式呼叫 return;closesocket() 函式 return 後,系统仍会继续将资料全部送完後,才真正地将这个 socket 关闭。一个 TCP socket 在开启时的预设值即是 Don''t Linger。
(3)SO_LINGER -- 适用於 TCP socket 来设定 linger 值之用。如果 linger的值设为 0,那麽在呼叫 closesocket() 关闭 socket 时,如果该 socket 的 output buffer 中还有资料的话,将会被系统所忽略,而不会被送出,此时 closesocket() 也会马上return;如果 linger 值设为 n 秒,那麽系统就会在这个时间内,尝试去送出 output buffer 中的资料,时间到了或是资料送完了,才会从 closesocket() 呼叫 return。
(4)SO_REUSEADDR -- 允许 socket 呼叫 bind() 去设定一个已经用过的位址 (含 port number)。
我们就以设定某个 socket 的 linger 值为例,看看程式中该如何呼叫 setsockopt() 这个函式:
struct linger Linger;
Linger.l_onoff = 1; /* 开启 linger 设定*/
Linger.l_linger = n; /* 设定 linger 时间为 n 秒 */
setsockopt( s, SOL_SOCKET, SO_LINGER, &Linger, sizeof(struct linger) )
相对地,如果我们想要知道目前的某个 option 的设定值,那麽就可以利用getsockopt() 函式来取得。
◎ getsockopt():取得某一 Socket 目前某个 option 的设定值。
格式: int PASCAL FAR getsockopt( SOCKET s, int level, int optname, char FAR *optval, int FAR *optlen )
参数: s Socket 的识别码
level option 设定的 level
optname option 名称
optval option 的设定值
optlen option 设定值的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取目前 Socket的某些 options 设定值。
同样地,我们仍以取得某个 socket 的 linger 值为例,看一下程式中应该如何呼叫 getsockopt():
struct linger Linger;
int opt_len = sizeof(struct linger);
getsockopt( s, SOL_SOCKET, SO_LINGER, &Linger, &opt_len)
【什麽是 Blocking Hook 函式及如何设定自己的 Blocking Hook 函式】
什麽是「Blocking Hook」函式呢?在解释之前,我们要先来剖析一下 Winsock 1.1 提供的 Blocking 函式(如 accept、connect 等)的内部究竟做了哪些事?
在 Winsock Stack 的 Blocking 函式内部,除了会检查一些条件外(比如该应用程式是否已呼叫过 WSAStartup()?传入的参数是否正确?等等),便会进入一个类似下面的回圈:
for (;;) {
/* 执行 Blocking Hook 函式 */
while (BlockingHook());
/* 检查使用者是否已经呼叫了 WSACancelBlockingCall()? */
if (operation_cancelled())
break;
/* 检查动作是否完成了? */
if (operation_complete())
break;
}
现