Linux socket函数,linux下socket通信
Windows套接字选项
在前几章中,我们讨论了使用windows套接字的基本内容。现在,我们将探索其他一些可用的功能。在我们掌握了本章的概念之后,我们就为后面的windows sockets高级主题做好了准备。在本章中,我们将关注以下主题:
如何使用getsockopt(2)函数获取windows sockets选项值
如何使用setsockopt(2)函数设置windows sockets选项值
如何使用这些常见的windows套接字选项?
获取windows套接字选项
有时,程序需要确定当前为windows套接字设置了哪些选项。对于这个子程序库函数来说尤其如此,因为这个库函数不知道要对这个windows sockets做什么设置,而这个windows sockets需要作为参数传递。也许程序需要知道默认使用的缓冲区的大小,类似于流。
getsockopt函数允许我们获取windows套接字选项值。该功能的概要如下:
#包含sys/types.h
#包含sys/socket.h
int getsockopt(int s,
int级别,
int optname,
void *optval,
socklen _ t * opt len);
参数描述如下:
1要检查选项的windows套接字
2.选项检查所在的协议层级别。
3要检查的选项optname
4指针optval指向接收选项值的缓冲区
5指针optlen指向输入缓冲区的长度和返回的选项长度值。
该函数成功时返回0。当出现错误时,将返回-1,错误原因将存储在外部变量errno中。
layer参数表示我们想要访问选项的协议栈。通常我们需要使用以下之一:
SOL_SOCKET访问windows套接字层选项
SOL_TCP访问TCP层选项
我们在本章的讨论将集中在SOL_SOCKET层选项的使用上。
参数optname是一个整数值。此处使用的值首先由选定的电平参数决定。在指定的协议级别,optname参数将决定我们要访问哪个选项。下表列出了层和选项的一些组合值:
协议层选项名称
SOL_SOCKET SO_REUSEADDR
SOL_SOCKET SO_KKEPALIVE
SOL_SOCKET SO_LINGER
SOL _ SOCKET SO _广播
SOL_SOCKET SO_OOBINLINE
SOL_SOCKET SO_SNDBUF
SOL_SOCKET SO_RCVBUF
溶胶_插座SO _类型
SOL _ SOCKET SO _错误
SOL_TCP SO_NODELAY
表中列出的大多数选项都是windows套接字选项,其中层由SOL_SOCKET指定。为了便于比较,包含了一个TCP层windows sockets选项,其中该层由SOL_TCP指定。
大多数windows sockets选项在获得后都以int数据类型存储。当查看手册页时,通常有一些关于数据类型int的假设,除非另有说明。使用布尔值时,当值非零时,int表示真,为零时表示假。
使用getsockopt(2)
在本部分中,我们将编译并运行一个getsndrcv.c程序,该程序将获取并报告一个windows sockets的发送和接收缓冲区的大小。
/*getsndrc.v
*
* Get SO_SNDBUF SO_RCVBUF选项:
*/
#包含stdio.h
#包含stdlib.h
#包含字符串. h
#包括unistd.h
#包含错误号h
#包含sys/types.h
#包含sys/socket.h
#include assert.h
/*
*该函数报告错误并
*出口回到外壳:
*/
静态无效保释(const char *on_what)
{
如果(errno!=0)
{
fputs(strerror(errno),stderr);
fputs(:,stderr);
}
fputs(on_what,stderr);
fputc(/n ,stderr);
出口(1);
}
int main(int argc,char **argv)
{
int z;
int s=-1;/*套接字*/
int snd buf=0;/*发送缓冲区大小*/
int rcvbuf=0;/*接收缓冲区大小*/
socklen _ t optlen/*选项长度*/
/*
*创建要使用的TCP/IP套接字:
*/
s=socket(PF_INET,SOCK_STREAM,0);
如果(s==-1)
提环(插座(2));
/*
*获取套接字选项SO_SNDBUF:
*/
optlen=sizeof sndbuf
z=getsockopt(s,SOL_SOCKET,SO_SNDBUF,SNDBUF,opt len);
如果(z)
保释( getsockopt(s,SOL_SOCKET,
SO _ SNDBUF));
assert(opt len==sizeof snd buf);
/*
*获取套接字选项SON_RCVBUF:
*/
optlen=sizeof rcvbuf
z=getsockopt(s,SOL_SOCKET,SO_RCVBUF,RCVBUF,opt len);
如果(z)
保释( getsockopt(s,SOL_SOCKET,
SO _ RCVBUF));
assert(opt len==sizeof rcvbuf);
/*
*报告缓冲区大小:
*/
printf(套接字s: %d/n ,s);
printf(Send buf: %d bytes/n ,sndbuf);
printf(Recv buf: %d bytes/n ,rcvbuf);
关闭;
返回0;
}
程序的运行结果如下:
$ ./getsndrcv
插座学生3
发送缓冲区:65535字节
接收缓冲区:65535字节
设置套接口选项
如果认为套接口的默认发送以及接收缓冲区的尺寸太大时,作为程序设计者的我们可以将其设计为一个小的缓冲区。当我们程序一个程序的几个实例同时运行在我们的系统上时,这显得尤其重要。
可以通过setsockopt(2)函数来设计套接口选项。这个函数的概要如下:
#包含sys/types.h
#包含sys/socket.h
int setsockopt(int s,
(同Internationalorganizations)国际组织级别,
int optname,
const void *optval,
socklen _ t opt len);
这个函数与我们在上面所讨论的取端口设置函数类似,setsockopt函数的参数描述如下:
一选项改变所要影响的套接口s
2选项的套接口层次水平
3要设计的选项名选项
四指向要为新选项所设置的值的指针optval
5选项值长度为缓冲区的长度
这个函数参数与上面的取端口设置函数的参数的区别就在于最后一个参数仅是传递参数值。在这种情况下只是一个输入值。
应用套接字选项函数
下面的例子代码为一个套接口改变了发送以及接收缓冲区的尺寸。在设置完这些选项以后,程序会得到并报告实际的缓冲区尺寸。
/*setsndrcv.c
*
*设置SO_SNDBUF SO_RCVBUF选项:
*/
#包含标准视频
#包含标准库
#包括unistd.h
#包含字符串。h
#包含错误号h
#包含sys/types.h
#包含sys/socket.h
#include assert.h
/*
*该函数报告错误并
*出口回到外壳:
*/
静态无效保释(const char *on_what)
{
如果(errno!=0)
{
fputs(strerror(errno),stderr);
fputs(:,stderr);
}
fputs(on_what,stderr);
fputc(/n ,stderr);
出口(1);
}
int main(int argc,char **argv)
{
int z;
int s=-1;/*套接字*/
int snd buf=0;/*发送缓冲区大小*/
int rcvbuf=0;/*接收缓冲区大小*/
socklen _ t optlen/*选项长度*/
/*
*创建要使用的传输控制协议套接字:
*/
s=socket(PF_INET,SOCK_STREAM,0);
如果(s==-1)
提环(插座(2));
/*
*设置SO_SNDBUF大小:
*/
sndbuf=5000/*发送缓冲区大小*/
z=setsockopt(s,SOL_SOCKET,SO_SNDBUF,SNDBUF,sizeof snd buf);
如果(z)
bail(setsockopt(s,SOL_SOCKET,
SO _ SNDBUF));
/*
*设置SO_RCVBUF大小:
*/
rcvbuf=8192/*接收缓冲区大小*/
z=setsockopt(s,SOL_SOCKET,SO_RCVBUF,RCVBUF,sizeof RCVBUF);
如果(z)
bail(setsockopt(s,SOL_SOCKET,
SO _ RCVBUF));
/*
*作为对上述内容的检查.
*获取套接字选项SO_SNDBUF:
*/
optlen=sizeof sndbuf
z=getsockopt(s,SOL_SOCKET,SO_SNDBUF,SNDBUF,opt len);
如果(z)
保释( getsockopt(s,SOL_SOCKET,
SO _ SNDBUF));
assert(opt len==sizeof snd buf);
/*
*获取套接字选项SO_RCVBUF:
*/
optlen=sizeof rcvbuf
z=getsockopt(s,SOL_SOCKET,SO_RCVBUF,RCVBUF,opt len);
如果(z)
bail(getsockopt(s,SOL_SOCKET
SO _ RCVBUF));
assert(opt len==sizeof rcvbuf);
/*
*报告缓冲区大小:
*/
printf(套接字s: %d/n ,s);
printf( Send buf: %d bytes/n ,sndbuf);
printf( Recv buf: %d bytes/n ,rcvbuf);
关闭;
返回0;
}
程序的运行结果如下:
$ ./setsndrcv
插座学生3
发送缓冲区:10000字节
接收缓冲区:16384字节
$
在这里我们要注意程序所报告的结果。他们看上去似乎是所指定的原始尺寸的两倍。这个原因可以由Linux操作系统操作系统内核源码模块网/芯/袜中查到。我们可以查看一下SO_SNDBUF以及SO_RCVBUF的情况语句。下面一段是由内核模块袜子。c中摘录的一段处理SO_SNDBUF的代码:
398案例SO_SNDBUF:
399 /*不要在这个加州大学伯克利分校软件(Berkeley Software Distribution)上出错,如果你认为
大约400英镑,这是对的。否则应用程序必须
401人玩"猜最大尺码"游戏RCVBUF/SNDBUF
402在加州大学伯克利分校软件(Berkeley Software Distribution)中被视为提示*/
403
404 if (val sysctl_wmem_max)
405 val=sysctl _ wmem _ max
406 set_sndbuf:
407 sk-sk _ user locks =SOCK _ snd buf _ LOCK;
408 if ((val * 2) SOCK_MIN_SNDBUF)
409 sk-sk _ snd buf=SOCK _ MIN _ snd buf;
410其他
411 sk-sk _ snd buf=val * 2;
412
413 /*
414 *唤醒发送任务如果我们
415 *提高了价值。
416 */
417 sk-sk _ write _ space(sk);
418破;
由这段代码我们可以看到实际发生在SO_SNDBUF上的事情:
一检测SO_SNDBUF选项值来确定他是否超过了缓冲区的最大值
2如果步骤一中的SO_SNDBUF选项值没有超过最大值,那么就使用这个最大值,而不会向调用者返回错误代码
3如果SO_SNDBUF选项值的2倍小于套接口SO_SNDBUF的最小值,那么实际的SO_SNDBUF则会设置为SO_SNDBUF的最小值,否则则会SO_SNDBUF选项值则会设置为SO_SNDBUF选项值的2倍
从这里我们可以看出SO_SNDBUF的选项值只是所用的一个提示值。内核会最终确定为SO_SNDBUF所用的最佳值。
查看更多的内核源码,我们可以看到类似的情况也适用于SO_RCVBUF选项。如下面的一段摘录的代码:
427案例SO_RCVBUF:
428 /*不要在这个加州大学伯克利分校软件(Berkeley Software Distribution)上出错,如果你认为
429关于它这是正确的。否则应用程序必须
430人玩"猜最大尺码"游戏RCVBUF/SNDBUF
431在加州大学伯克利分校软件(Berkeley Software Distribution)中被视为提示*/
432
433 if (val sysctl_rmem_max)
434 val=sysctl _ rmem _ max
435 set_rcvbuf:
436 sk-sk _ user locks =SOCK _ RCVBUF _ LOCK;
437 /*
438 *我们在来的路上翻了一倍
439 * struct sk_buff 等。开销。应用程序
440 *假设他们进行的SO_RCVBUF设置将
441 *允许在其上接收大量实际数据
442 *插座。
443 *
444 *应用程序不知道"结构sk_buff "和
445 *从接收缓冲区分配的其他开销
446 *在套接字缓冲区分配期间。
447 *
在考虑了可能的替代方案后,
449 *返回我们在取端口设置中实际使用的值
450 *是最可取的行为。
451 */
452 if ((val * 2) SOCK_MIN_RCVBUF)
453 sk-sk _ RCVBUF=SOCK _ MIN _ RCVBUF;
454其他
455 sk-sk _ rcvbuf=val * 2;
456破;
取得套接口类型
实际上我们只可以得到一些套接口选项。SO_TYPE就是其中的一例。这个选项会允许传递套接口的一个子函数来确定正在处理的是哪一种套接口类型。
如下面是一段得到套接口s类型的示例代码:
/*gettype.c
*
*获取SO_TYPE选项:
*/
#包含标准视频
#包含标准库
#包括unistd.h
#包含字符串。h
#包含错误号h
#包含sys/types.h
#包含sys/socket.h
#include assert.h
/*
*该函数报告错误并
*出口回到外壳:
*/
静态无效保释(const char *on_what)
{
如果(errno!=0)
{
fputs(strerror(errno),stderr);
fputs(:,stderr);
}
fputs(on_what,stderr);
fputc(/n ,stderr);
出口(1);
}
int main(int argc,char **argv)
{
int z;
int s=-1;/*套接字*/
int so _ type=-1;/*插座类型*/
socklen _ t optlen/*选项长度*/
/*
*创建要使用的TCP/IP套接字:
*/
s=socket(PF_INET,SOCK_STREAM,0);
如果(s==-1)
提环(插座(2));
/*
*获取套接字选项SO_TYPE:
*/
optlen=sizeof so _ type
z=getsockopt(s,SOL_SOCKET,SO_TYPE,so_type,opt len);
如果(z)
保释( getsockopt(s,SOL_SOCKET,
SO _ TYPE));
assert(opt len==sizeof so _ type);
/*
*报告结果:
*/
printf(套接字s: %d/n ,s);
printf( SO_TYPE : %d/n ,SO _ TYPE);
printf( SO_STREAM=%d/n ,SOCK _ STREAM);
关闭;
返回0;
}
程序的运行结果如下:
$./gettype
插座学生3
SO_TYPE : 1
SO_STREAM=1
设置SO_REUSEADDR选项
在第11章,并发客户端服务器的第一部分中,提供并测试了一个使用叉系统调用设计的服务器。图12.1显示了在一个远程登录命令与服务器建立连接之后的三个步骤。
这些步骤如下:
一启动服务器进程(PID 926)。他监听客户端连接。
2启动客户端进程(远程登录命令),并且连接到服务器进程(PID 926)。
3通过叉调用创建服务器子进程,这会保留的原始的父进程(PID 926)并且创建一个新的子进程(PID 927)。
4.连接的客户端windows套接字由服务器父进程关闭(PID 926),只有连接的客户端windows套接字进程在子进程中打开(PID 927)。
5 telnet命令与服务器子进程(PID 927)自由交互,独立于父进程(PID 926)。
在步骤5中,有两个windows套接字活动:
服务器(PID 926)监听192.168.0.1: 9099
客户端由windows套接字192.168.0.1: 9099 (PID 927)提供服务,它连接到客户端地址192.168.0.2: 1035。
客户端由进程ID 927提供服务。这意味着我们可以终止进程ID 926,客户端仍然可以得到服务。但是,不会有到服务器的新连接,因为没有服务器侦听新连接(侦听服务器PID 926已被终止)。
现在,如果我们重新启动服务器来监听新的连接,就会出现问题。当新的服务器进程试图绑定IP地址192.168.0.1: 9099时,bind函数将返回错误代码EADDRINUSE。此错误代码表示IP已被用于端口9099。这是因为进程PID 927仍然忙于服务客户端。该进程仍然使用地址192.168.0.1: 9099。
这个问题的解决方案是终止进程927,它关闭windows套接字并释放IP地址和端口。然而,如果被服务的客户是我们公司的CEO,这种方法似乎不是一个选项。同时,其他部门也会抱怨我们为什么要重启服务器。
解决这个问题的一个好办法是使用SO_REUSEADDR windows sockets选项。所有服务器都应该使用这个选项,除非有更好的理由不使用它。为了有效地使用此选项,我们应该在监视连接的服务器中执行以下操作:
1使用通常的套接字函数创建一个监听windows套接字。
2调用setsockopt函数将SO_REUSEADDR设置为TRUE
3调用绑定函数
Windows套接字现在被标记为可重用。如果监控服务器进程因任何原因终止,我们可以重新启动该服务器。当客户端对另一个服务器进程使用相同的IP和端口号时,尤其如此。
为了有效地使用SO_REUSEADDR选项,需要考虑以下情况:
监听模式下没有相同IP地址和端口号的其他windows套接字
具有相同IP地址和端口号的所有windows套接字都必须将SO_REUSEADDR选项设置为TRUE。
这意味着对于给定的IP地址和端口号对,只能使用一个侦听器。如果这样的windows sockets已经存在,设置这样的选项将无法实现我们的目标。
只有当所有具有相同地址和端口号的windows套接字都有此选项时,将SO_REUSEADDR设置为TRUE才会有效。如果现有的windows套接字没有设置此选项,绑定功能将继续,并将返回一个错误号。
以下代码显示了如何将此选项设置为TRUE:
#定义正确1
#定义假0
int z;/*状态代码*/
int s;/*插座数量*/
int so _ reuseaddr=TRUE
z=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,
so_reuseaddr,
sizeof so _ reuse addr);
如果需要SO_REUSEADDR选项,可以通过getsockopt函数查询。
设置SO_LINGER选项
另一个常见的选项是SO_LINGER选项。与SO_REUSEADDR选项不同,该选项中使用的数据类型不是简单的int类型。
SO_LINGER选项的目的是控制调用close函数时如何关闭windows套接字。此选项仅适用于面向连接的协议,如TCP。
内核的默认行为是允许close函数立即返回给调用者。任何未发送的TCP/IP数据都有可能被传输,但这不能保证。因为close函数会立即将控制权返回给调用者,所以程序无法知道最后一位数据是否已经发送。
可以将SO_LINGER选项应用到windows sockets中,使程序阻塞close函数的调用,直到所有最后的数据都传输到远程端。此外,这将确保两端的调用都知道windows套接字通常是关闭的。如果失败,指定的选项将超时,并向调用方返回一个错误。
通过使用SO_LINGER选项的不同值,可以应用最终场景。如果调用者想要立即停止通信,它可以在linger结构中设置一个适当的值。然后,调用close将初始化通信中断连接,丢弃所有未发送的数据,并立即关闭windows套接字。
SO_linger的这种运行模式是由linger结构控制的:
结构逗留{
int l _ onoff
int l _ linger
};
成员l_onoff是一个布尔值,非零值表示TRUE,零值表示FALSE。该选项的三个值描述如下:
将l_onoff设置为FALSE会导致忽略成员l_linger,并使用默认的关闭行为。也就是说,关闭的调用将立即返回给调用者,如果可能的话,任何未发送的数据将被传输。
将2 l_onoff设置为TRUE将使成员l_linger的值变得重要。当l_linger为非零值时,这表示应用于close函数调用的超时时间(秒)。如果在超时发生之前有未发送的数据,并且成功关闭,则函数将成功返回。否则,将返回一个错误,变量errno的值将被设置为EWOULDBLOCK。
将3 l_onoff设置为TRUE并将l_linger设置为零会导致连接中止,并且在调用close时会丢弃任何发送的数据。
也许我们希望得到一些建议,在我们的程序中使用SO_LINGER选项,并提供一个合理的超时期限。然后,您可以检查close函数的返回值,以确定连接是否成功关闭。如果返回一个错误,它告诉我们的程序,也许远程程序不能接收我们发送的所有数据。相反,他可能只是指连接关闭时的问题。
但是,我们必须保持清醒,这种方法会在一些服务器设计中产生新的问题。当SO_LINGER选项被配置为在close函数调用中超时(LINGER)时,当我们的服务器在close函数调用中执行time out时,其他客户端将被阻止服务。如果我们在一个进程中服务多个客户端进程,就会存在这个问题。使用默认行为可能更合适,因为它允许close函数立即返回。任何未发送的数据将继续发送给内核。
最后,如果程序或服务器知道何时应该停止连接,它可以使用停止行为。当服务器认为没有访问权限的用户试图访问时,可能会出现这种情况。这种情况下的客户不会得到特别的关注。
以下代码是使用SO_LINGER选项的示例,超时时间为30秒:
#定义正确1
#定义假0
int z;/*状态代码
*/int s;/*套接字s */
struct linger so _ linger
.
so _ linger.l _ onoff=TRUE
so _ linger.l _ linger=30
z=setsockopt(s,
SOL_SOCKET,
所以_灵儿,
所以_灵儿,
sizeof so _ linger);
如果(z)
perror( setsockopt(2));
以下示例显示了如何设置SO_LINGER的值来终止windows套接字上的当前连接:
#定义正确1
#定义假0
int z;/*状态代码*/
int s;/*套接字s */
struct linger so _ linger
.
so _ linger.l _ onoff=TRUE
so _ linger . l _ linger=0;
z=setsockopt(s,
SOL_SOCKET,
所以_灵儿,
所以_灵儿,
sizeof so _ linger);
如果(z)
perror( setsockopt(2));
关闭;/*中止连接*/
在上面的例子中,当close函数被调用时,windows sockets将立即停止。中止的语义是通过将超时值设置为0来实现的。
设置SO_KKEPALIVE选项
在使用连接时,有时他们会闲置相当长的时间。例如,通过访问股票交易服务建立一个telnet会话。也许他会执行一些初始查询,然后离开连接并保持服务开放,因为他想回来查询更多内容。然而,同时连接处理是空闲的,可能一次一个小时。
当任何一个服务器认为它有一个连接的客户端时,就会给它分配相应的资源。如果服务器是一个fork,那么整个Linux进程及其对应的内存都分配给这个客户。如果事情进展顺利,这个场景不会引起任何问题。然而,当网络崩溃时,困难就出现了,我们所有的578名客户都将失去与我们股票交易服务的联系。
网络服务恢复后,578个客户将尝试连接到我们的服务器并重新建立连接。这对我们来说是一个现实问题,因为我们的服务器之前没有意识到他失去了闲置客户——所以_ kkepalive来解决这个问题。
以下示例显示了如何在windows sockets上使用SO_KKEPALIVE选项,以便可以检测到断开的空闲连接:
#定义正确1
#定义假0
int z;/*状态代码*/int s;/*套接字s */
int so _ keepalive
.
so _ keepalive=TRUE
z=setsockopt(s,
SOL_SOCKET,
所以_KEEPALIVE,
所以_keepalive,
sizeof so _ keepalive);
如果(z)
perror( setsockopt(2));
在上面的例子中,设置了SO_KEEPALIVE选项,这样当windows sockets连接长时间空闲时,就会向远端发送一个探测消息。这通常是在两个小时不活动后完成的。对保活探测消息有三种可能的响应。它们是:
1 end会适当返回,表示一切正常。没有指示信息返回到程序,因为这是程序的假定开始。
最终响应表明他对该连接一无所知。这表明自上次通信以来,此端已重新与主机连接。这样,在执行下一个windows套接字操作时,ECONNRESET错误代码将返回给程序。
终端3没有响应。在这种情况下,内核可能会多次尝试连接。如果请求没有响应,TCP通常会在11分钟左右放弃。发生这种情况时,下一个windows套接字操作将返回ETIMEOUT错误。当网络无法再连接到主机时,将返回其他错误,如EHOSTUNREACH。
SO_KEEPALIVE调用的时间帧会限制其平时的使用。只有在大约两个小时不活动后,才会发送探测信息。然后,当没有响应时,又过了11分钟,连接才返回错误。在任何情况下,该选项都允许服务器检测空闲的无连接windows套接字,然后将其关闭。相应地,支持长时间空闲连接的服务器应该允许这个特性。
设置SO_BROADCAST选项
我们还没有讨论使用UDP广播的话题。然而,我们很容易意识到广播功能的误用以及由此带来的网络灾难。为了避免在没有预定广播时广播,windows sockets禁用了广播功能。如果真的需要广播,那么C程序员就要为windows sockets的这个功能处理相应的麻烦。
SO_BROADCAST是一个布尔标志选项,由int数据类型设置。以下示例显示了如何设置SO_BROADCAST选项:
#定义正确1
#定义假0
int z;/*状态代码*/
int s;/*套接字s */
int so _ broadcast
.
so _ broadcast=TRUE
z=setsockopt(s,
SOL_SOCKET,
所以_广播,
所以_广播,
sizeof so _ broadcast);
如果(z)
perror( setsockopt(2));
如果想让setsockopt函数返回零,windows sockets已经允许广播了。不过这里需要注意的是,选择的windows sockets类型必须有广播功能,比如UDP windows sockets。
设置SO_OOBINLINE选项。
在某些情况下,发送的数据可能会超过限制的数据量。通常,这些越界数据是通过使用不同的数据接收函数来接收的。但是,有时候我更喜欢用通常的方式接收这些越界的数据。选择此方法时,越界数据作为正常数据流的一部分先于正常数据到达。
要使用此功能,我们可以使用以下代码:
#定义正确1
#定义假0
int z;/*状态代码*/
int s;/*套接字s */
int so _ oobinline
.
so _ oobinline=TRUE
z=setsockopt(s,
SOL_SOCKET,
SO_OOBINLINE,
so_oobinline,
sizeof so _ oo binline);
如果(z)
perror( setsockopt(2));
设置SO_OOBINLINE选项后,越界数据将与正常数据一起接收。这样,接收到的越界数据就和平时的数据一样了。
SO_PASSCRED和SO_PEERCRED选项
这些选项仅适用于PF_UNIX(PF_LOCAL) windows套接字。这些选项用于在当前主机的本地windows套接字上控制和传递凭据。这也许是最难掌握的科目。现在,我们只需要注意,如果我们想编写一个服务程序来服务本地主机客户,我们可能会对这两个选项感兴趣。