多网口UDP发包无法收到回包排查与解决

news/2024/10/22 8:26:50/

最近几周几乎都是单休,加班很多,也遇到了很多未知的问题,杂事也多时间比较紧张,也没有多少空余来进行一些总结积累。这点让我很是怀念起几年前的日子,任务安排周期长,做技术纯粹又专心。

前几天遇到了一个UDP发包无法收到回包的问题,趁着今天不加班来记录回顾一下。

网络环境

两台主机,每台主机上分别有两个网口。

主机1的Ip地址:

  • 管理口:192.168.1.2
  • 网口一:2006:470:8192:beef:6114:e3d6:a597:aea6
  • 网口二:2006:470:8192:beef:d45e:a0fa:9c9c:2e4b

主机2的Ip地址:

  • 管理口:192.168.1.3
  • 网口一:2005:470:8192:beef:9020:c015:a801:1301
  • 网口二:2005:470:8192:beef:68af:d2e6:a0e3:6fb1

如下图:
tp

udpServer

func udpServerStart() {srcAddr := &net.UDPAddr{IP:   net.IPv6zero,Port: 12345,}//监听不绑定IPconn, _ := net.ListenUDP("udp6", srcAddr)fmt.Printf("udp server bind on:[%s]\n", conn.LocalAddr())for {buffer := make([]byte, 1024)//将数据读到buffer中n, remoteAddr, _ := conn.ReadFromUDP(buffer)fmt.Printf("remote addr:[%s] \n data:[%v] str:[%s]\n", remoteAddr.String(), buffer[:n], string(buffer[:n]))//发送回包_, _ = conn.WriteToUDP([]byte("hello client"), remoteAddr)}
}

udpClient

再写个httpServer,在"udpTest"接口中实现个udpClient,用来发udp数据包

func httpServerStart() {udpTestHandler := func(writer http.ResponseWriter, request *http.Request) {ipStr := request.FormValue("ip")fmt.Printf("req param,ip:[%s]\n", net.ParseIP(ipStr))socket, err := net.DialUDP("udp6", nil,&net.UDPAddr{IP:   net.ParseIP(ipStr),Port: 12345,},)if err != nil {fmt.Println("连接UDP服务器失败,err: ", err)return}defer socket.Close()sendData := []byte("Hello Server")_, err = socket.Write(sendData) // 发送数据if err != nil {fmt.Println("发送数据失败,err: ", err)return}data := make([]byte, 4096)n, remoteAddr, err := socket.ReadFromUDP(data) // 接收数据if err != nil {fmt.Println("接收数据失败, err: ", err)return}fmt.Printf("recv:%v addr:%v count:%v\n", string(data[:n]), remoteAddr, n)}handler := http.NewServeMux()handler.Handle("/udpTest", http.TimeoutHandler(http.HandlerFunc(udpTestHandler), time.Second*3, "timeout"))server := &http.Server{Addr: ":8096", Handler: handler}err := server.ListenAndServe()if nil != err {log.Fatal(err) //显示错误日志}
}

发包测试

在主机1上向主机2的两个端口发包

http://192.168.1.2:8096/udpTest?ip=2005:470:8192:beef:68af:d2e6:a0e3:6fb1
http://192.168.1.3:8096/udpTest?ip=2005:470:8192:beef:9020:c015:a801:1301

主机1没有日志打印,且http接口都显示超时了。

观察主机2的日志:

udp server bind on:[[::]:12345]remote addr:[[2003:470:8192:beef:ca43:6a6a:9c4c:b1a0]:48406] data:[[72 101 108 108 111 32 83 101 114 118 101 114]] str:[Hello Server]
reply addr:[[2003:470:8192:beef:ca43:6a6a:9c4c:b1a0]:48406] length:12 remote addr:[[2003:470:8192:beef:ca43:6a6a:9c4c:b1a0]:35365] data:[[72 101 108 108 111 32 83 101 114 118 101 114]] str:[Hello Server]
reply addr:[[2003:470:8192:beef:ca43:6a6a:9c4c:b1a0]:35365] length:12 

主机2收到了udp包,也发送了回包。
但主机1没有并没有收到,包走丢了?

主机2上用tcpdump抓个包看一下
host2pcap

看到主机2只收到了主机1的udp包,但没有回包发出去,那么回包发到哪去了?

问题定位

因为之前有试过主机1和主机2的tcp和http请求都是通的,但UDP却不通确实感到疑惑。
我们知道http是基于TCP的,UDP和TCP相比也是更加简单的,也无需握手。

查阅了一些资料后发现扯淡的文档居多,直到遇到了这篇好文《Linux路由应用-使用策略路由实现访问控制》,重点片段为:

UDP无连接,不可靠,只负责将数据尽力而为传到目的主机,它对源和目的IP地址的管理很松散,UDP数据流(更确切的并不能称为数据流)是单包的。在两端都没有显式bind到具体的IP地址的情况下,最终的数据包可以使用任意的本机地址,关键看路由的结果。数据到达对端之后,如果对端也没有显示bind到具体的IP地址,那么回复包的源地址也可能不再是初始包的目的地址。

解决办法

其解决办法在《Linux路由应用-使用策略路由实现访问控制》文章中也描述了可以使用配置系统策略路由的方式来解决,这里再总结一下。

方法一:配置策略路由

这部分参考《Linux路由应用-使用策略路由实现访问控制》文章中添加策略路由表部分即可。

方法二:配置系统路由

如果通信时很明确知道数据包是发往某个口的,则可以添加一条系统默认路由来解决。如:

ip -6 route add ::/0 dev ppp0 metric 60

这样当主机二再进行回包时,就会指定使用ppp0口进行回包了。

也可以通过udp进行socket通信时获取到包中的目的地址,再从UDP包中获取出源地址灵活添加系统路由配置。
常见的方式为,可以通过开启IPPROTO_IP进行获取。
如为go语言实现,可通过如下代码开启:

    syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1)

再调用ReadMsgUDP就可以获取到的具体的目的IP了。
详细代码可参考:
udp_ip_pktinfo.go

方法三:udp server绑定具体的IP

当然还有最后一种简单有用的方法,udp server进行监听时对每个网口的ip地址都进行一次绑定,简单方便。


http://www.ppmy.cn/news/665274.html

相关文章

拓展屏无信号显示-解决方案

下载驱动精灵,更新显卡驱动

笔记本外接的显示器突然不能用,显示无信号

重装win10识别不出双屏第二个显示器解决方法_U教授 (ujiaoshou.com) 参照上述步骤去更新驱动,如果还是不行,就把驱动“禁用”然后再“启用”

戴尔服务器无视频信号,开启电脑 显示器提示无视频信号

1.硬盘灯不亮,请检查主板跳线,你拆开清理后,很有可能是HDD-LED这个线没接上。一般是不需要注意正负的,但是不排除有一些特别的主板。 2.显示器提示无视频信号,那就是主机没有给到显示器信号,主机开机硬件自…

计算机屏幕无信号咋回事,电脑显示屏无信号怎么回事?电脑打不开显示器无信号的解决办法...

有的朋友一定要到过这样的问题,电脑一开机显示器就显示无信号,请检查视频输入,主机运行应该正常,风扇转着,连接线也重新插拔过,这时为什么呢?下面我们就来介绍电脑显示器无信号的解决方法。 电脑…

苹果产品存显示屏缺陷,却仍在销售

本文转载自IT之家 IT之家 4 月 2 日消息 2019 年,一些购买 2016 年和 2017 年 MacBook Pro 机型的用户开始注意到屏幕上会出现一种奇怪的 “舞台灯光”现象,这种奇怪的现象是由一根脆弱的柔性线缆造成的,该线缆会随着电脑的反复打开和关闭而…

android实现启动未声明的Activity

实现原理:首先创建一个占位StubActivity,这个Activity必须要添加声明,用来代替目标的Activity,然后在ActivityThread中的Handler回调中替换掉原来的Callback,改为自己的Callback,并在此修改成自己要启动的真…

电脑计算机怎么没有桌面显示器,显示器无信号,教您电脑显示屏不显示怎么修复...

电脑使用久了,就什么问题都会碰见的,有的用户是看淡了,可是对于电脑新手来说却是一个不小的打击,如果电脑出现一开机显示器就显示无信号,主机运行应该正常,风扇转着,连接线也重新插拔过&#xf…

开机后,电脑显示屏无信号怎么办?

转自:微点阅读(www.weidianyuedu.com)微点阅读 - 范文大全 - 免费学习知识的网站 随着使用电脑的用户越来越多,而使用的用户遇到的问题就越多了,而经常用电脑的同学大部分都遇到过电脑显示器无信号的情况吧。其实相比显…