62-UDP 与 connect

在上一篇文章中,非常详细的叙述了有连接和无连接的区别,并严格的定义了什么是有连接。然后讲解了使用 connect 函数将 UDP 套接字设置成有连接的。

本文我们继续讨论有连接和无连接 UDP 的区别。

1. 多次调用 connect 函数

上一讲我们已经知道 connect 函数可以把 UDP 套接字设置成有连接的。但是如果多次调用 connect 会怎样呢?主要有以下两个目的:

  • 重新指定 peername
  • 断开连接,即删除 peername(也可能会删除 sockname)

对于第一个目的来说,很简单,只要设置好正确的套接字地址,传参给 connect 即可。

对于第二个目的来说,需要将套接字地址结构体 struct sockaddr 中的 sin_family 成员设置成 AF_UNSPEC,见下面的代码.

struct sockaddr_in disconnaddr; memset(&disconnaddr, 0, sizeof(disconnaddr)); disconnaddr.sin_family = AF_UNSPEC; // 断开连接 connect(sockfd, &disconnaddr, sizeof(disconnaddr));

2. 有连接与无连接 UDP 的性能

2.1 无连接

在无连接 UDP 套接字上调用 sendto 时,Berkele 的内核会暂时连接该套接字, 发送数据报,然后断开该连接。比如下面这断代码:

// 连接两次调用 sendto sendto(sockfd, buf, 100, 0, &servaddr, sizeof(servaddr)); sendto(sockfd, buf, 200, 0, &servaddr, sizeof(servaddr));

它会执行下面 6 个步骤:

  • 连接套接字
  • 发送第一个数据报
  • 断开套接字连接
  • 连接套接字
  • 发送第二个数据报
  • 断开套接字连接

第一次连接需要为目的 IP 地址搜索路由表,并进行缓存。第二次连接,会直接到缓存中取。

2.2 有连接

同样的,对于 2.1 中的代码来说,有连接套接字是这样做的:

connect(sockfd, &servaddr, sizeof(servaddr)); write(sockfd, buf, 100); write(sockfd, buf, 200);

它会执行下面的步骤:

  • 连接套接字
  • 发送第一个数据报
  • 发送第二个数据报

这种情况下,内核只复制一次含有目的 ip 和 port 的套接字地址,而使用 sendto 时,需要复制两次。文献 [1] 指出,临时连接未连接的 UDP 套接字大约会耗费每个 UDP 传输三分之一的开销。

3. 参考文献

[1] Partridge C, Pink S. A faster UDP [user datagram protocol][J]. IEEE/ACM Transactions on Networking, 1993, 1(4):429-440.

说明:本文转自blog.csdn.net,用于学习交流分享,仅代表原文作者观点。如有疑问,请联系我们删除~