UDP之connect

在UDP中,也是可以调用connect系统调用的。但是其作用并不是TCP中的与服务器发起三次握手,他只是在系统中注册对端的地址,以供后面使用。
因为在udp编程中,如果需要发送数据给对端,那么需要使用sendTo函数,在参数中指明对端的地址,此时系统所做的事情是,先调用connect函数(注册对端),接着再发送数据,然后再调用connect函数(取消注册)。如果先调用connect函数的话,那么在以后的发送数据时,就不需要使用sendTo函数了(也不能使用),直接使用send和receive函数就可以进行数据的发送和接受了。因为调用connect注册后,此时系统默认该UDP只能与注册的对端发生数据交互,不能与其他的对端进行通信,所以在发送数据的时候就不需要使用sendto了。而至于receive,在调用connect后,如果不是所注册的对端发来的数据,系统会默认将其丢掉,只接受所注册的对端发来的数据。UDP编程使用connect系统调用,具体有以下几个特点:

  1. TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来.

  2. UDP中可以多次调用connect,TCP只能调用一次connect.(UDP多次调用connect有两种用途:1,指定一个新的ip&port连结. 2,断开和之前的ip&port的连结)

  3. 对于连续向相同的对端发送数据时,调用connect可以提高效率,因为每一次的sendto都需要经过三个阶段:建立连接-》发送数据-》断开连接
  4. 采用connect的UDP发送接受报文可以调用send,write和recv,read操作.当然也可以调用sendto,recvfrom. 调用sendto的时候第五个参数必须是NULL,第六个参数是0.调用recvfrom,recv,read系统调用只能获取到先前connect的ip&port发送的报文.
  5. 由已连接的UDP套接口引发的异步错误,返回给他们所在的进程。相反未连接UDP套接口不接收任何异步错误给一个UDP套接口。如果对端没启动,默认情况下发送的包对应的ICMP回射包不会给调用进程,调用了connect之后就可以收到该错误。

第6点主要是因为在UDP规则中,如果收到UDP数据报而且目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。所有的ICMP差错报告报文中的数据字段都具有同样的格式。将收到的需要进行差错报告IP数据报的首部和数据字段的前8个字节提取出来,作为ICMP报文的数据字段。再加上响应的ICMP差错报告报文的前8个字节,就构成了ICMP差错报告报文。提取收到的数据报的数据字段的前8个字节是为了得到运输层的端口号(对于TCP和UDP)以及运输层报文的发送序号(对于TCP)。

从发送到收到icmp是有一定的时延的, 如果是Sendto往二个目的地址写数据报,此时1成功1失败,这种情况下如果这时候内核收到icmp报文,就不知道是哪个sendto。虽然icmp可以获得传输层的端口,但是在sendTo的目的ip和端口一样的情况下,也不能辨别出是哪一个sendto造成的。