UDP也是一样可以进行connect的,和TCP的区别在于没有三次握手而已,但是同样也是可以使用send,recv来进行同通信。getpeername并不是说只能用于TCP的,准确的说,getpeername只能用于已连接的SOCKET,这是什么意思呢?就是说如果使用UDP,但是调用了connect函数的话,那么同样服务器端可以用getpeername来获得连入客户端的地址。
对于已连接udp套接口(调用过connect),与缺省的未连接udp套接口相比,发生了三个变化:
1.不能给输出操作指定宿ip地址和套接口。也就是说,不能使用sendto(),而改写write或send。写到已连接udp套接口上的任何内容都自动发送到connect指定的协议地址。
2.不能使用recvfrom以获悉数据报的发送者,而改用read、recv或recvmsg。在一个已连接udp套接口上由内核为输入操作返回的数据报仅仅是那些来自connect所指定协议地址的数据报。目的地为这个已连接udp套接口的本地协议,发源地却不是该套接口早先connect到的协议地址的数据报,不会投递到该套接口。这样就限制一个已连接udp套接口能且仅能与一个对端交换数据报。
3.由已连接udp套接口引发的异步错误返回给它们所在的进程。相反,未连接udp套接口不接受任何异步错误。
拥有一个已连接udp套接口的进程可为下列两个目的之一再次调用connect:
A.指定新的ip地址和端口号
B.断开套接口。
为了断开一个已连接udp套接口,再次调用connect时把套接口地址结构的地址族成员设置为AF_UNSPEC。这么做可能返回一个EAFNOSUPPORT错误,不过没关系。使得套接口断开连接的是在已连接udp套接口上调用connect的进程。
已连接udp套接口还可用来确定用于某个特定目的地的外出接口。这是有connect函数应用到udp套接口时的一个副作用造成的:内核选择本地ip地址(假设其进程未曾调用bind显式指派它)。这个本地ip地址通过为宿ip地址搜索路由表得到外出接口,然后选用该接口的主ip地址而选定。在udp套接口上调用connect并不给对端主机发送任何信息,它完全是一个本地操作,只是保存对端的ip地址和端口号。在一个未绑定端口号的udp套接口上调用connect同时也给该套接口指派一个临时端口。
在UDP套接口编程中使用connect会带来一些额外的好处:
在末连接UDP套接字上给两个数据报调用函数sendto导致内核执行下列六步:
1.连接套接字;
2.输出第一个数据报
3.断开套接字连接;
4.连接套接字,
5.输出第二个数据报;
6.断开套接字连接
已连接UDP套接字发送两个数据报的导致内核执行如下步骤;
1.连接套接字;
2.输出第一个数据报;
3.输出第二个数据报。
所以,对同一UDP套接字发送时,某种程度上来讲,耗时减少1/3。
另外还有如下的其它一些好处:
1)选定了对端,内核只会将帮定对象的对端发来的数据报传给套接口,因此在一定环境下可以提升安全性;
2)会返回异步错误,如果对端没启动,默认情况下发送的包对应的ICMP回射包不会给调用进程,如果用了connect,则可以了