在Win7/Win8下傳送UDP廣播封包
在撰寫UDP的應用軟體時,有時候會遇到需要發送廣播封包的需求,而這種情況下,就會選擇使用UDP的方式來傳送,而最簡單的方式就是使用UdpClient來處理了;例如說在不知道對方的IP位置的情況,而對方有做類似IpSearch的功能時,就可以利用廣播的方式讓對方將自己目前的IP位置給傳送回來。
廣播封包的發送通常來說動作就是向255.255.255.255這個廣播位置去做資料的發送,然後再去讀取回送的資料,而本篇筆記主要是在Windows XP跟之後的作業系統(Windows7/WIndows8)之間的差異性
筆者在早期有撰寫了一個簡單的小軟體,來做廣播處理的動作,在發送UDP封包的部分,程式碼大致如下
在Windows XP上面一切相安無事,也能正常地從遠端抓到回傳的資料;但到了Windows 7之後,怪怪,不論如何都沒有辦法取回遠端的回應,而利用Wireshark之類的封包監控軟體去查看網路的傳送狀況,X! 任何東西都沒有送出來,開VM跑XP,同樣的程式又可以運作正常,這是啥狀況 Orz Orz
這個狀況一開始實在摸不著頭緒,直到今天想說再搜尋一下資料,總算理出一些端倪;解決方式的源頭來自下面這篇討論
http://stackoverflow.com/questions/6290329/why-is-my-udp-broadcast-failing
其中有一段提到
『Windows 7 handles 255.255.255.255 broadcast in a different way』
往下追之後才驚覺原來是作業系統對於廣播位址的處理不同了,而在Windows7/Windows8要綁定一個IP地址之後才能正常的發送以及接收了,有了這個線索之後,轉而利用socket來處理,並且修改相關程式碼如下
改用這個方式總算能夠正常的在Windows 8的作業系統上正常的傳送以及接收UDP的廣播封包了;拖了好長時間,總算能夠宣布破案! 相關動作特別筆記一下,以免年紀大了失憶情況嚴重 XD
廣播封包的發送通常來說動作就是向255.255.255.255這個廣播位置去做資料的發送,然後再去讀取回送的資料,而本篇筆記主要是在Windows XP跟之後的作業系統(Windows7/WIndows8)之間的差異性
筆者在早期有撰寫了一個簡單的小軟體,來做廣播處理的動作,在發送UDP封包的部分,程式碼大致如下
Dim bEP As New IPEndPoint(IPAddress.Broadcast, 4550) Client = New UdpClient(4550, AddressFamily.InterNetwork) Client.EnableBroadcast = True Client.Send(btySend, btySend.Length, "255.255.255.255", 4550) Threading.Thread.Sleep(CInt(txtDelay.Text)) Do If Client.Available > 0 Then btyRecv = Client.Receive(bEP) If btyRecv IsNot Nothing AndAlso btyRecv.Length > 0 Then ''處理接收到資料後的事情 End If Else Exit Do End If Loop Client.Client.Close()
在Windows XP上面一切相安無事,也能正常地從遠端抓到回傳的資料;但到了Windows 7之後,怪怪,不論如何都沒有辦法取回遠端的回應,而利用Wireshark之類的封包監控軟體去查看網路的傳送狀況,X! 任何東西都沒有送出來,開VM跑XP,同樣的程式又可以運作正常,這是啥狀況 Orz Orz
這個狀況一開始實在摸不著頭緒,直到今天想說再搜尋一下資料,總算理出一些端倪;解決方式的源頭來自下面這篇討論
http://stackoverflow.com/questions/6290329/why-is-my-udp-broadcast-failing
其中有一段提到
『Windows 7 handles 255.255.255.255 broadcast in a different way』
往下追之後才驚覺原來是作業系統對於廣播位址的處理不同了,而在Windows7/Windows8要綁定一個IP地址之後才能正常的發送以及接收了,有了這個線索之後,轉而利用socket來處理,並且修改相關程式碼如下
Dim bEP As New IPEndPoint(IPAddress.Any, 4550) Dim s As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim host As IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName) For Each IP As IPAddress In host.AddressList If (IP.AddressFamily = AddressFamily.InterNetwork) Then s.Bind(New IPEndPoint(IP, 4550)) Exit For End If Next s.EnableBroadcast = True s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, True) s.SendTo(btySend, New IPEndPoint(IPAddress.Broadcast, 4550)) For i As Integer = 0 To 30 Threading.Thread.Sleep(100) Application.DoEvents() Next ReDim btyRecv(1024) Do If s.Available > 0 Then Dim aa As Integer = s.ReceiveFrom(btyRecv, bEP) If btyRecv IsNot Nothing AndAlso aa >= 76 Then ''處理接收到資料後的事情 End If Else Exit Do End If Loop s.Close() s = Nothing
改用這個方式總算能夠正常的在Windows 8的作業系統上正常的傳送以及接收UDP的廣播封包了;拖了好長時間,總算能夠宣布破案! 相關動作特別筆記一下,以免年紀大了失憶情況嚴重 XD
留言