美文网首页LinuxLinux学习之路
APUE读书笔记-16网络通信(9)

APUE读书笔记-16网络通信(9)

作者: QuietHeart | 来源:发表于2020-08-03 17:40 被阅读0次

6、套接字选项

套接字机制提供了两个套接字选项接口来控制套接字的行为。一个接口用来设置选项,另外一个接口用来允许我们请求选项的状态。

我们可以获得以及设置三种类型的选项。

  1. 通用选项,可以工作在所有的套接字类型。
  2. 在套接字层次上面进行管理的选项,但是依赖底部协议的支持。
  3. 和每个协议相关的协议选项。

Single UNIX Specification 只定义了套接字层的选项(上面所提到的前面两项)

setsockopt

我们可以通过setsockopt函数来设置套接字选项。

#include <sys/socket.h>
int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len);

返回:如果成功返回0,如果错误返回1。

参数level用来分辨option所应用的协议。如果option是通用套接字层次的选项,那么level设置成SOL_SOCKET。否则level设置成控制option的协议号。例如IPPROTO_TCP用于TCP选项,以及IPPROTO_IP用于IP选项。下面的表中就列出了Single UNIX Specification定义的通用的套接字层次的选项。

                                                套接字选项
+-------------------------------------------------------------------------------------------------------------+
|    Option     | Type of val argument |                             Description                              |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_ACCEPTCONN | int                  | 返回套接字是否激活用于侦听(只用于getsockopt)。                     |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_BROADCAST  | int                  | 如果*val非0那么广播数据报。                                          |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_DEBUG      | int                  | 如果*val非0那么激活网络驱动的调试。                                  |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_DONTROUTE  | int                  | 如果*val非0,那么忽略通常的路由。                                    |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_ERROR      | int                  | 返回并且清除提交的套接字错误(只用于getsockopt)。                   |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_KEEPALIVE  | int                  | 如果*val非0,那么激活定期活动的消息。                                |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_LINGER     | struct linger        | 如果有未发送的消息存在以及套接字关闭,那么做延迟。                   |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_OOBINLINE  | int                  | 如果*val非0,那么将带外数据嵌入到正常数据中。                        |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_RCVBUF     | int                  | 接收缓存的字节大小。                                                 |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_RCVLOWAT   | int                  | receive调用返回的最小数据字节。                                      |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_RCVTIMEO   | struct timeval       | 套接字receive调用的超时值。                                          |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_REUSEADDR  | int                  | 如果*val非0,那么重复使用bind的地址。                                |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_SNDBUF     | int                  | send缓存中的字节大小。                                               |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_SNDLOWAT   | int                  | 一次send调用传输的最小数据字节量。                                   |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_SNDTIMEO   | struct timeval       | 一个套接字send调用的超时值。                                         |
|---------------+----------------------+----------------------------------------------------------------------|
| SO_TYPE       | int                  | 辨别套接字类型(只在getsockopt中)。                                 |
+-------------------------------------------------------------------------------------------------------------+

参数val指向一个数据结构或者整数,这取决于option。有些选项是on/off开关。 如果这个整数非0,那么option被激活。如果这个整数是0,那么option不被激活。len参数指定val指向的对象的大小。

getsockopt

我们可以通过函数getsockopt来获取当前option的值。

#include <sys/socket.h>
int getsockopt(int sockfd, int level, int option, void *restrict val, socklen_t *restrict lenp);

返回:如果成功返回0,如果错误返回1。

注意 lenp参数是一个指向整数的指针 。在调用getsockopt之前,我们设置整数为option被拷贝的缓存的大小,如果实际的option大小比这个大小大,那么option就会被截断。如果实际的option大小比size小或者同样大,那么整数会在返回的时候被更新成实际的大小。

例子

前面的(initserver)函数当服务进程终止的时候操作失败,然后我们尝试立即重新启动。一般来说,TCP的实现会会阻止我们将同样一个地址绑定,除非超时。SO_REUSEADDR的套接字选项允许我们忽略这个限制,下面的代码就展示了这个特性。

为了激活SO_REUSEADDR选项,我们设置整数为一个非0的值然后将整数的地址做为val参数传递给setsockopt函数。我们设置len参数为一个表示整数的大小,来表示val所指向的对象的大小。

服务进程使用地址重用初始化一个将要被使用的套接字末端

#include "apue.h"
#include <errno.h>
#include <sys/socket.h>
int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen)
{
    int fd, err;
    int reuse = 1;

    if ((fd = socket(addr->sa_family, type, 0)) < 0)
        return(-1);
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {
        err = errno;
        goto errout;
    }
    if (bind(fd, addr, alen) < 0) {
        err = errno;
        goto errout;
    }
    if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
        if (listen(fd, qlen) < 0) {
            err = errno;
            goto errout;
        }
    }
    return(fd);

errout:
    close(fd);
    errno = err;
    return(-1);
}

译者注

原文参考

参考: APUE2/ch16lev1sec6.html

相关文章

  • APUE读书笔记-16网络通信(9)

    6、套接字选项 套接字机制提供了两个套接字选项接口来控制套接字的行为。一个接口用来设置选项,另外一个接口用来允许我...

  • APUE读书笔记-16网络通信(2)

    3、寻址 在前面的小节里面,我们学到了如何创建和销毁一个套接字。在我们使用套接字之前,我们需要知道如何定位到我们交...

  • APUE读书笔记-16网络通信(5)

    4、建立连接 如果我们处理一个面向连接的网络服务(SOCK_STREAM或者SOCK_SEQPACKET),那么在...

  • APUE读书笔记-16网络通信(4)

    (4)将地址和套接字进行关联 客户的套接字关联的地址并不是重点,我们可以让系统选择一个默认的地址。但是对于一个服务...

  • APUE读书笔记-16网络通信(7)

    面向连接与面向无连接通讯举例 面向连接的客户端的例子 下面的程序,显示了一个客户的命令,这个命令和服务进行通信,从...

  • APUE读书笔记-16网络通信(10)

    7、带外数据 带外数据是一个被一些通信协议支持的可选的特性,它允许比普通数据优先级高的数据被传送。带外数据会被优先...

  • APUE读书笔记-16网络通信(1)

    1、简介 在前面的章节,我们查看了pipes,FIFOs,消息队列,信号量,和共享内存这些unix提供的经典的IP...

  • APUE读书笔记-16网络通信(6)

    5、数据传输 由于socket末端使用文件描述符号来替代,当被连接起来的时候,我们就可以使用read和write来...

  • APUE读书笔记-16网络通信(3)

    (3)地址查询 理想情况,一个应用程序不用知道套接字地址的内部结构。如果一个应用程序简单地把套接字地址作为sock...

  • APUE读书笔记-16网络通信(8)

    无连接客户的例子 下面的程序就是使用数据包接口的uptime客户端程序。 基于数据包的客户端的main函数和面向连...

网友评论

    本文标题:APUE读书笔记-16网络通信(9)

    本文链接:https://www.haomeiwen.com/subject/nwijlktx.html