• UDP 连接


    1. UDP connect

    我们经常说UDP是无连接的传输协议, 如果UDP调用connect呢? 会发生什么?
    UDP套接字调用connect函数, 跟TCP连接调用connect不一样: 没有三次握手过程. 而且, 内核只是检查是否存在立即可知的错误(e.g. 一个显然不可达的目的地, 由于非法端口/ip地址等原因), 记录对端的IP地址和端口号(取自传递给connect的套接字地址结构), 然后立即返回到调用进程.
    用sockname是本地协议地址, peername是对端协议地址, 那么UDP connect(已连接UDP套接字)更好的名字是setpeername, UDP bind更好的名字是setsockname.

    因此, UDP connect并不是在通信两端之间真正建立了可靠连接, 而只是设置对端协议地址.

    1.1 UDP连接的概念

    • 未连接UDP套接字(unconnected UDP socket), 新创建UDP套接字默认;
    • 已连接UDP套接字(connected UDP socket), 对UDP套接字调用connect的结果;

    1.2 未连接UDP套接字 与 已连接UDP套接字

    已连接UDP套接字在未连接UDP套接字 (默认)基础上, 发生了变化:
    1)不能给输出操作指定目的IP地址和端口号. i.e. 不能使用sendto(传入目的地址结构, 如果非要使用sendto, 地址结构参数必须为NULL), 而改用write或read. 因为写已连接UDP套接字上的任何内容, 都自动发送到由connect指定的对端协议地址(IP地址+端口号);

    TCP和UDP套接字: 可指定目的协议地址吗?

    套接字类型 write或send 不指定目的地址的
    sendto
    指定目的地址的
    sendto
    TCP套接字 可以 可以 EISCONN
    UDP套接字, 已连接 可以 可以 EISCONN
    UDP套接字, 未连接 EDESTADDRREQ EDESTADDRREQ 可以

    2)不必使用recvfrom以获取数据报的发送者, 改用read, recv或recvmsg.
    缺点: 内核返回的数据报, 只有那些来自connect所指定对端协议地址的数据报. 也就是说, 接收到的数据报中, 如果源地址 != connect指定对端地址, 则进程不会接收到.

    问题: 进程不收到的UDP报文, 会如何处理?
    可能投递到同一主机上的其他某个UDP套接字. 如果没有相匹配的其他套接字, UDP将丢弃并生成相应的ICMP不可达错误.

    3)由已连接UDP套接字引发的异步错误会返回给它们所在的进程, 而未连接UDP套接字不接收任何异步错误.

    小结
    UDP套接字何时调用connect?
    当UDP客户进程或服务器进程只使用自己的UDP套接字与确定的唯一对端进行通信时, 才调用connect. 调用connect的通常是UDP客户, 少数情况下可能UDP服务器, 如UDP服务器与单个客户长时间通信(TFTP).

    1.2 多次调用connect

    一个已连接UDP套接字的进程, 何时可以再次调用connect?

    1. 指定新的IP地址和端口号;
    2. 断开套接字;

    注意: 对于TCP套接字, 只能调用一次connect.

    对于1), 类似于第一次调用connect方式, 为connect指定新的IP地址和端口号;
    对于2), 再次调用connect时, 需要把套接字地址结构中的地址族成员(IPv4为sin_family, IPv6为sin6_family) 设置为AF_UNSPEC. 可能返回EAFNOSUPPORT错误, 不过没关系, 忽略即可.
    不同Unix变体可能有多种办法断开连接, 不过, 用AF_UNSPEC传递给connect的sa_family是最通用的方法.

    而且, man connect(2)提到, 断开套接字连接, 应该用AF_UNSPEC传递给connect的sa_family

    Generally, connection-based protocol sockets may successfully connect() only once; connectionless
    protocol sockets may use connect() multiple times to change their association. Connectionless
    sockets may dissolve the association by connecting to an address with the sa_family member of
    sockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).

    1.3 性能

    多次发送数据时, 已连接UDP套接字效率 > 未连接UDP套接字效率.

    UNP 8.11.2提到, 临时连接未连接的UDP套接字大约会耗费每个UDP传输三分之一的开销.

    以2次发送数据报为例,
    未连接UDP套接字调用2次 sendto发送数据报, 然后断开连接. 执行步骤:
    1)连接套接字;
    2)输出第一个数据报;
    3)断开套接字连接;
    4)连接套接字;
    5)输出第二个数据报;
    6)断开套接字连接;

    内核复制2次IP地址+端口号

    已连接UDP套接字调用1次connect连接, 2次write发送数据报. 执行步骤:
    1)连接套接字;
    2)输出第一个数据报;
    3)输出第二个数据报;

    内核复制1次IP地址+端口号

  • 相关阅读:
    第一阶段冲刺02
    梦断代码阅读笔记01
    第一阶段冲刺01
    第十周总结报告
    单词统计
    用户模板分析
    第九周总结
    第九周课后作业
    py_11_ 0726
    Day_01
  • 原文地址:https://www.cnblogs.com/fortunely/p/14861004.html
Copyright © 2020-2023  润新知