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.

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值