UDP 的 connect()
- 前方提到,如果使用的是 UDP 套接字进行通信的话,可以采取
connect
来进行优化,但是却不知原因。 - 首先 UDP 的别称叫做 不可靠连接 , 也就是说它可以不需要对发送出去的数据负责任,在默认情况下这是对的,因为效率。
- 但是如果一个 UDP 套接字端 需要与另一个端进行多于一次的通信的时候,就会出现性能问题:
- 具体是:
连接两端通信 -> 发送数据 -> 断开连接 -> 连接两端通信 -> 发送数据 -> 断开连接 ......
- 可以看出,需要重复的进行 连接和断开, 且这两个操作都是涉及 内核 操作,耗费的资源不可忽略
- 所以在必要时对 UDP 套接字调用
connect
,是有必要的(并不硬性要求两端同时都要调用connect
) - 需要注意的是 TCP 套接字 同样需要调用(必须调用)
connect
,虽然调用的函数接口一样,但是意义却是不相同的,前者是为了三次握手建立连接,而 UDP 却只是为了能够省去 不必要的断开连接 以及接收到 ICMP错误报文 。
- 具体是:
- ICMP 错误报文,指的是如果对端没办法接收到本端发送的信息的话,会返回一个错误,这个错误使用的就是 ICMP (ICMPv4和ICMPv6两种)
- 如果 UDP 套接字通信时采用的是 未连接(unconnected) 的形式,那么在调用
sendto
接口之后,不管对端有没有收到信息,都会立即返回成功的信息,而即使对端没办法收到信息,且向本端发送了 ICMP 报文,我们也是无法检测到的。 - 但是如果 UDP 套接字通信时采用的是 连接(connected) 的形式,那么就会接收到一个
EHOSTUNREACH
的错误,我们就能够捕捉到(这点与TCP的处理方式一样)。
- 如果 UDP 套接字通信时采用的是 未连接(unconnected) 的形式,那么在调用
- 假设我们想要断开连接 或者 重新选择一个对端进行通信,也是可以的
- 所需要做的也仅仅是在此调用一下
connect
接口函数struct sockaddr_storage unconnect; memset(&unconnect, 0, sizeof unconnect); unconnect.ss_family = AF_UNSPEC; /* 将 xxx_family 位置为 AF_UNSPEC 就表明要断开连接 */ connect(udp_sock, (struct sockaddr *)&unconnect, sizeof unconnect); /* 断开连接 */
- 所需要做的也仅仅是在此调用一下
注: 断开连接或者重新对套接字建连接是 UDP 才可以使用的,千万不要用在 TCP套接字上面!
- 和 TCP 这种面向连接的方式不同, UDP 不管是否是连接的(connected),它依旧是一种不可靠的传输方式,所以当它调用
connect
时,即使对端没有运行,这个函数也不会有任何错误,知道发送第一条信息时才能知道对端到底可不可达。