上一节最后发现服务端不存在客服端并不知道, 会被一直阻塞.
错误回顾
如果你忘了启动服务端, 你会发现客服端依旧被阻塞了, 并且没有报错. 而且发送数据即使没有收到应答的数据也没有报错, 程序仍然处于阻塞状态.
错误解析
其实在客服端与服务端主机发送UDP数据报之前, 需要一次arp请求和应答交换(我是在一个主机上实验, 所以无法抓取到).
我们在通过抓包可以看到,服务端会响应一个port unreachable
的ICMP应答, 不过这个ICMP并不会返回给客户进程, 这个错误是sendto
导致的, 而sendto
将数据发送出去之后就返回成功了, 而ICMP是在之后才发出来, 所以这个错误也称ICMP异步错误
.
而这个错误只会在已连接时, 才会返回给客服进程. 说了这么多次已连接, 那么接下来我们就来看一下怎么才能让UDP已连接.
UDP已连接
客服端通过调用connect
完成UDP已连接的状态, 但不同于TCP, UDP调用connect
不会出现三次握手的现象, 只是用来记录对端的IP地址和端口号, 然后返回给调用进程.
已连接的UDP相对于未连接的UDP发生部分变化 :
- 不再给
recvfrom
输出上面绑定IP地址和端口号, 也不用让sendto
获取对端的IP地址和端口号信息; 也就是可以直接调用write
和read
函数. - 可以收到ICMP异步错误.
注意 : UDP使用connect
没有三次握手并使connect并不会阻塞, 而是直接返回.
服务端的代码不用就行修改, 客服端的代码修改如下 :
完整代码 : connect_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include