zoukankan      html  css  js  c++  java
  • 【网络编程】TCPIP-8-套接字的多种选项


    前言

    说明:

    • demo 基于 Linux。

    8. 套接字的多种选项

    一般创建好套接字后直接使用即可,有些配置是默认的,当然也可以通过以下修改。

    8.1 API getsockopt(); & setsockopt();

    /*
    sock: 用于查看选项套接字文件描述符
    level: 要查看的可选项协议层
    optname: 要查看的可选项名
    optval: 保存查看结果的缓冲地址值
    optlen: 向第四个参数传递的缓冲大小。调用函数候,该变量中保存通过第四个参数返回的可选项信息的字节数。
    成功时返回 0 ,失败时返回 -1
    */
    #include <sys/socket.h>
    int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
    
    /*
    sock: 用于更改选项套接字文件描述符
    level: 要更改的可选项协议层
    optname: 要更改的可选项名
    optval: 保存更改结果的缓冲地址值
    optlen: 向第四个参数传递的缓冲大小。调用函数候,该变量中保存通过第四个参数返回的可选项信息的字节数。
    成功时返回 0 ,失败时返回 -1
    */
    #include <sys/socket.h>
    int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
    

    8.2 套接字选项

    注意,套接字可选项是分层的。

    • SOL_SOCKET:套接字的通用可选项。
    • IPPROTO_TCP:可选项是 TCP 协议的相关事项。
    • IPPROTO_IP:IP 协议相关事项。
    协议层 选项名 读取 设置
    SOL_SOCKET SO_SNDBUF O O
    SOL_SOCKET SO_RCVBUF O O
    SOL_SOCKET SO_REUSEADDR O O
    SOL_SOCKET SO_KEEPALIVE O O
    SOL_SOCKET SO_BROADCAST O O
    SOL_SOCKET SO_DONTROUTE O O
    SOL_SOCKET SO_OOBINLINE O O
    SOL_SOCKET SO_ERROR O X
    SOL_SOCKET SO_TYPE O X
    IPPROTO_IP IP_TOS O O
    IPPROTO_IP IP_TTL O O
    IPPROTO_IP IP_MULTICAST_TTL O O
    IPPROTO_IP IP_MULTICAST_LOOP O O
    IPPROTO_IP IP_MULTICAST_IF O O
    IPPROTO_TCP TCP_KEEPALIVE O O
    IPPROTO_TCP TCP_NODELAY O O
    IPPROTO_TCP TCP_MAXSEG O O

    8.3 缓冲区相关可选项

    SO_SNDBUF & SO_RCVBUF

    SO_SNDBUF

    • 输出缓冲区相关的可选项。
    • 可用其读取当前 I/O 大小,也可以更改缓冲区大小。

    SO_RCVBUF

    • 输入缓冲区相关的可选项。
    • 可用其读取当前 I/O 大小,也可以更改缓冲区大小。

    8.4 端口复用

    主要用到 SO_REUSEADDR

    先了解一些概念再介绍该选项。

    8.4.1 time-wait 状态

    MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

    time-wait 状态一般为 2 个MSL。其原因:

    • 保证 TCP 协议的全双工连接能够可靠关闭。
    • 保证这次连接的重复数据段从网络中消失。保证下次连接收到的数据报文段都是来自新连接的目标端。
    • 返回ACK最长为也给MSL,如果没有到达对端,对端重发,到本端最大也要一个MSL,所以得2个MSL

    若服务器先异常断开,四次挥手后进入 time-wait 状态(一般为几分钟),在 time-wait 状态时,该端口还是被占用的。服务器重启后不能正常使用该端口,会输出「bind() error」消息。必须等待该端口被置为 close 状态才能被正常使用。

    但是有些情景下是不能接受的,若服务器异常重启,那得等待几分钟才能正常使用。
    解决:使用SO_REUSEADDR来解决。

    8.4.2 SO_REUSEADDR使用

    在套接字的可选项中更改 SO_REUSEADDR 的状态。
    适当调整该参数,可将 Time-wait 状态下的套接字端口号重新分配给新的套接字。
    SO_REUSEADDR 的默认值为 0。
    这就意味着无法分配 Time-wait 状态下的套接字端口号。
    因此需要将这个值改成 1 。

    参考:

    option = TRUE;
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
    

    8.4.3 SO_REUSEADDR 作用

    SO_REUSEADDR 作用:

    1. 当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
    2. SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
    3. SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
    4. SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

    8.5 Nagle 算法

    主要用到 TCP_NODELAY

    Nagle 算法

    • 应用于 TCP 层。
    • TCP 套接字默认使用 Nagle 算法交换数据。
    • 算法:只有接收到前一数据的 ACK 消息, Nagle 算法才发送下一数据。

    禁用

    opt_val = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, sizeof(opt_val));
    

    查看

    getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, sizeof(opt_val));
    

    参考

  • 相关阅读:
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1056:点和正方形的关系
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1058:求一元二次方程
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1058:求一元二次方程
    《工程数学——线性代数》—— 第1章——行列式 —— § 2 全排列和对换
    《工程数学——线性代数》—— 第1章——行列式 —— § 2 全排列和对换
    《工程数学——线性代数》—— 第1章——行列式 —— § 2 全排列和对换
    《工程数学——线性代数》—— 第1章——行列式 —— § 1 二阶与三阶行列式
    【Javascript】【jQuery】onload和onready的区别
    【Javascript】【jQuery】onload和onready的区别
    使用T4模板映射数据库表
  • 原文地址:https://www.cnblogs.com/lizhuming/p/15169754.html
Copyright © 2011-2022 走看看