当前位置: 首页 > 科技观察

令人困惑的SocketUDP连接问题

时间:2023-03-13 08:00:35 科技观察

公司内部的一个golang中间件报UDP连接日志异常。问题很明显。另一端的服务宕机了,自然可以重启。哈哈,不过让我比较困惑的问题是udp是怎么检测到peer挂了的呢?.0.46:29999:write:connectionrefuserr:writeudp172.16.44.62:62651->172.16.0.46:29999:write:connectionrefused...UDP协议既没有三向握手也没有TCP状态控制消息,所以如何确定对端UDP端口是否打开?通过抓包可以发现,当server端的端口没有打开的时候,server端的系统向client返回一个icmpECONNREFUSED报文,表示连接异常。通过抓包可以发现返回的协议是ICMP,但是包含了源端口和目的端口。客户端系统解析消息时,通过五元组找到对应的socket,返回异常错误errno。如果客户端卡在等待中,则唤醒并设置错误状态。(上面是udp异常下的icmp,下面是正常的icmp)当UDP连接异常时,可以使用tcpdump工具指定ICMP协议抓取异常报文。毕竟对方是通过icmp返回ECONNREFUSED的。使用tcpdump抓包请求命令:先找到一个可以ping通的主机,然后用nc模拟一个udp客户端去请求一个不存在的端口,出现Connectionrefused。[root@ocean~]#nc-vzu172.16.0.468888Ncat:版本7.50(https://nmap.org/ncat)Ncat:连接到172.16.0.46:8888.Ncat:连接被拒绝。捕获信息如下:[root@ocean~]#tcpdump-ianyicmp-nntcpdump:verboseoutputsuppressed,use-vor-vvforfullprotocoldecodelisteningonany,link-typeLINUX_SLL(Linuxcooked),捕获大小262144字节17:01:14.075617IP172.16。0.46>172.16.0.62:ICMP172.16.0.46udpport8888unreachable,length3717:01:17.326145IP172.16.0.46>172.16.0.62:ICMP172.16.0.46udpport8888unreachable,length3717:01:17.927480IP172.16.0.46>172.16.0.62:ICMP172.16.0.46udpport8888unreachable,length3717:01:18.489560IP172.16.0.46>172.16.0.62:ICMP172.16.0.46netudpport8888unreachable,length支持tcp检测,推荐使用ncUDP。各种情况测试用例总结ip无法连接时,udp客户端连接时,一般显示成功。当udpserver程序关闭,但系统还存在时,其他系统会出现`icmpECONNREFUSE错误。对方操作iptablesudpportdrop时,通常客户端也会显示success。IP无法连接时:[root@host-46~]$ping172.16.0.65PING172.16.0.65(172.16.0.65)56(84)bytesofdata.From172.16.0.46icmp_seq=1DestinationHostUnreachableFrom172.16.0.46icmp_seq2DestinationHostUnreachableFrom172.16.0.46icmp_seq=3DestinationHostUnreachableFrom172.16.0.46icmp_seq=4DestinationHostUnreachableFrom172.16.0.46icmp_seq=5DestinationHostUnreachableFrom172.16.0.46icmp_seq=6DestinationHostUnreach-1^0ping2.6-able统计---6个数据包传输,0个接收,+6个错误,100%数据包丢失,时间4999mspipe4[root@host-46~]$nc-vzu172.16.0.658888Ncat:Version7.50(https://nmap.org/ncat)Ncat:连接到172.16.0.65:8888.Ncat:UDP数据包发送成功Ncat:发送1个字节,2.02秒内接收到0个字节。另外,再次明确udp不像tcp那样有状态报文,所以对于UDP只是简单的抓包,看不到任何异常信息。那为什么在IP不可达的情况下NCUDP命令显示成功呢?为什么netcatncudp的逻辑在ip未连接或消息DROP时返回连接成功?因为nc默认的检测逻辑很简单,只要在2秒内没有收到icmpECONNREFUSED异常报文,就认为UDP连接成功。