UDP 连接要不要发起 connect
什么是 UDP
让我们先来看看 wiki 的定义
In computer networking, the User Datagram Protocol (UDP) is one of the core members of the Internet protocol suite. The protocol was designed by David P. Reed in 1980 and formally defined in RFC 768. With UDP, computer applications can send messages, in this case referred to as datagrams, to other hosts on an Internet Protocol (IP) network. Prior communications are not required in order to set up communication channels or data paths.
UDP uses a simple connectionless communication model with a minimum of protocol mechanisms. UDP provides checksums for data integrity, and port numbers for addressing different functions at the source and destination of the datagram. It has no handshaking dialogues, and thus exposes the user's program to any unreliability of the underlying network; there is no guarantee of delivery, ordering, or duplicate protection. If error-correction facilities are needed at the network interface level, an application may use Transmission Control Protocol (TCP) or Stream Control Transmission Protocol (SCTP) which are designed for this purpose.
UDP is suitable for purposes where error checking and correction are either not necessary or are performed in the application; UDP avoids the overhead of such processing in the protocol stack. Time-sensitive applications often use UDP because dropping packets is preferable to waiting for packets delayed due to retransmission, which may not be an option in a real-time system.[1]
划重点:
UDP 是基于 IP 协议的
不需要预先建立通道来发送数据
开销很小,没有传输必达保证,没有排序,没有去重
应用层做错误监测
适用于对于丢包不敏感的场景
C 层面的 UDP 编程
问题:UDP 发送到底要不要首先发起 connect 调用
参考连接 1
https://www.geeksforgeeks.org/udp-server-client-implementation-c/
参考连接 2
https://www.geeksforgeeks.org/udp-client-server-using-connect-c-implementation/
非常有意思的是,大部分例子都分成两类:
一类不带 connect 函数,一类带 connect 函数,那么 UDP 发送,到底要不要首先发起 connect 调用呢?
让我们来看看 connect 函数的定义:
https://man7.org/linux/man-pages/man2/connect.2.html
根据定义,还是不是很清楚,让我们再看看 stack 的答疑https://stackoverflow.com/questions/9741392/can-you-bind-and-connect-both-ends-of-a-udp-connection
An ordinary UDP socket doesn't know anything about its future destinations, so it performs a route lookup each time sendmsg() is called.
However, if connect()
is called beforehand with a particular remote receiver's IP and port, the operating system kernel will be able to write down the reference to the route and assign it to the socket, making it significantly faster to send a message if subsequent sendmsg()
calls do not specify a receiver (otherwise the previous setting would be ignored), choosing the default one instead.
connect() on a SOCK_DGRAM socket sets the default/send receive address, so then you can just use send and recv. I'm writing it to work over TCP as well so that ends up making some other code common to both protocols.
简单总结一下:
调用 connect,可以绑定接收发送地址,后续可以直接使用 send/receive 函数,使得 UDP/TCP 编程模型可以保持一致
connect 函数绑定地址后,可以避免查询内核查询 route 表,更快,效率更高
所以要不要使用 connect 函数,还是取决于应用场景。
如果你的目标 UDP 服务器不变,那么 connect 之后发送接收,效率更高,并且编程模型,可以与 TCP 保持一致
如果你的 UDP 服务器地址不确定,那么不要 connect。
Go 层面的 UDP 编程
根据 go 的编程模型来看,write 函数并未指定目标服务器地址,我们可以推测,在之前的 net.DialUDP 操作中,做了之前说到的 connect 操作,将地址与 socket 进行了绑定,后续发送接收就不需要再携带服务器地址了。
查看下 net.DialUDP 的源码,socket_posix.go 里
是不是看到了熟悉的 connect 方法 :)
Java 层面的 UDP 编程
待续。。。
版权声明: 本文为 InfoQ 作者【kof11321】的原创文章。
原文链接:【http://xie.infoq.cn/article/78de4c59ed5f4b911ad2f87bd】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论