none
使用udpClient廣播 沒辦法接收到回來的封包 RRS feed

  • 問題

  • 各位大大好唷

    最近再做一個 廣播的軟體

    當我從255.255.255.255廣播位址 廣播後

    我使用Ethereal 查看封包

    我定 每台機器都有收到我的廣播且回應給我

    但是 我程式碼 在接收的地方 就停住不動了

    麻煩幫我看看 是哪個地方出了問題

     

    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text
    Imports System.Threading


    Public Class Form1

        Private t As Threading.Thread
        Private udpClient As New UdpClient
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            udpClient.EnableBroadcast = True

            Try
                udpClient.Connect("255.255.255.255", 6990)

                Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes("MIDWAYANDJOSEPHNICQQ")

                UdpClient.Send(sendBytes, sendBytes.Length)


                'Dim RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, 0)

                'UdpClient.Receive blocks until a message is received from a remote host.
                'Dim receiveBytes As [Byte]() = UdpClient.Receive(RemoteIpEndPoint)
                'Dim returnData As String = Encoding.ASCII.GetString(receiveBytes)

                ' Which one of these two hosts responded?
                t = New Threading.Thread(AddressOf Receving)
                t.Start()

                'udpClient.Close()

            Catch ex As Exception
                Debug.Print(ex.ToString())
            End Try


        End Sub

        Public Sub Receving()
            'Thread.Sleep(2000)

            Dim RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, 0)

            Dim data() As Byte = udpClient.Receive(RemoteIpEndPoint)

    中斷點就停在這裡 RemoteIpEndPoint 的IP 為0

    下面的程式究不會執行

              請各位大大幫忙一下 未何會這樣

     


            Dim strData As String = Encoding.ASCII.GetString(data)
            Debug.Print(strData)

            Debug.Print((strData.ToString()))
            Debug.Print((RemoteIpEndPoint.Address.ToString() + "   " + RemoteIpEndPoint.Port.ToString()))
        End Sub
    End Class

    2008年4月3日 上午 09:48

解答

  • 之前測試的時候做的sample,參考看看

     

    兩個專案,
    UDPListener(等待連線用)
    Form1上有一個ListBox1

    Code Snippet

    Imports System
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text

    Public Class Form1

        Dim UDPL, UDPS As UdpClient
        Dim AnyEP, EP4662 As IPEndPoint
        Dim btyRecv As Byte()
        Dim btySend As Byte()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            UDPL = New UdpClient(4661)
            UDPL.EnableBroadcast = True
            AnyEP = New IPEndPoint(IPAddress.Any, 4661)
            EP4662 = New IPEndPoint(IPAddress.Parse("255.255.255.255"), 4662)
            btySend = Encoding.ASCII.GetBytes(Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString)
            Timer1.Enabled = True
        End Sub

        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If UDPL.Available > 0 Then
                btyRecv = UDPL.Receive(AnyEP)
                ListBox1.Items.Add(Encoding.ASCII.GetString(btyRecv, 0, btyRecv.Length))
                UDPL.Send(btySend, btySend.Length, EP4662)
            End If
            Application.DoEvents()
        End Sub
    End Class

     

     

    UDPSend(傳送指令用)
    Form1上有一個Button1,ListBox1

    Code Snippet

    Imports System
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text

    Public Class Form1

        Dim UDPL, UDPR As UdpClient
        Dim EP, AnyEP As IPEndPoint
        Dim B As Byte() = Encoding.ASCII.GetBytes("AAAAA")
        Dim btyRecv As Byte()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            UDPL = New UdpClient()
            UDPR = New UdpClient(4662)
            UDPR.EnableBroadcast = True
            UDPL.EnableBroadcast = True
            EP = New IPEndPoint(IPAddress.Parse("255.255.255.255"), 4661)
            AnyEP = New IPEndPoint(IPAddress.Any, 4661)
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            UDPL.Send(B, B.Length, EP)
            Timer1.Enabled = True
        End Sub

        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If UDPR.Available > 0 Then
                btyRecv = UDPR.Receive(AnyEP)
                ListBox1.Items.Add(Encoding.ASCII.GetString(btyRecv, 0, btyRecv.Length))
                Timer1.Enabled = False
            End If
            Application.DoEvents()
        End Sub
    End Class

     

     

    主要是聆聽端到訊息之後會把自己的IP位址傳回去
    2008年4月3日 上午 10:26
    版主
  • 已經過時的意思是說,這個"方法"是舊版的,已經有提供新的"方法"可以呼叫,因為我懶惰..沒有去修正..

    "已經過時"同時也表示將來新的版本不一定會有這個"方法"可以呼叫,有可能會拿掉的意思。

     

    另外,如果你不想用Timer的話,在Do...Loop的迴圈裡面除了 Doevents之外最好加上Threading.Sleep來放出CPU時間,不然在Do...Loop那段時間CPU會滿載

    2008年4月7日 上午 04:56
    版主

所有回覆

  • 之前測試的時候做的sample,參考看看

     

    兩個專案,
    UDPListener(等待連線用)
    Form1上有一個ListBox1

    Code Snippet

    Imports System
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text

    Public Class Form1

        Dim UDPL, UDPS As UdpClient
        Dim AnyEP, EP4662 As IPEndPoint
        Dim btyRecv As Byte()
        Dim btySend As Byte()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            UDPL = New UdpClient(4661)
            UDPL.EnableBroadcast = True
            AnyEP = New IPEndPoint(IPAddress.Any, 4661)
            EP4662 = New IPEndPoint(IPAddress.Parse("255.255.255.255"), 4662)
            btySend = Encoding.ASCII.GetBytes(Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString)
            Timer1.Enabled = True
        End Sub

        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If UDPL.Available > 0 Then
                btyRecv = UDPL.Receive(AnyEP)
                ListBox1.Items.Add(Encoding.ASCII.GetString(btyRecv, 0, btyRecv.Length))
                UDPL.Send(btySend, btySend.Length, EP4662)
            End If
            Application.DoEvents()
        End Sub
    End Class

     

     

    UDPSend(傳送指令用)
    Form1上有一個Button1,ListBox1

    Code Snippet

    Imports System
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text

    Public Class Form1

        Dim UDPL, UDPR As UdpClient
        Dim EP, AnyEP As IPEndPoint
        Dim B As Byte() = Encoding.ASCII.GetBytes("AAAAA")
        Dim btyRecv As Byte()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            UDPL = New UdpClient()
            UDPR = New UdpClient(4662)
            UDPR.EnableBroadcast = True
            UDPL.EnableBroadcast = True
            EP = New IPEndPoint(IPAddress.Parse("255.255.255.255"), 4661)
            AnyEP = New IPEndPoint(IPAddress.Any, 4661)
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            UDPL.Send(B, B.Length, EP)
            Timer1.Enabled = True
        End Sub

        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If UDPR.Available > 0 Then
                btyRecv = UDPR.Receive(AnyEP)
                ListBox1.Items.Add(Encoding.ASCII.GetString(btyRecv, 0, btyRecv.Length))
                Timer1.Enabled = False
            End If
            Application.DoEvents()
        End Sub
    End Class

     

     

    主要是聆聽端到訊息之後會把自己的IP位址傳回去
    2008年4月3日 上午 10:26
    版主
  •  

    謝謝大大唷

    我剛回南部 掃墓回來說

    明天到公司我在試看看

    2008年4月6日 上午 10:38
  • OK 了大大

    收的回來了

     

    我將大大給我的 依造我所需要的改寫

    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text
    Imports Microsoft.VisualBasic

    Public Class Form1
        Dim UDPL, UDPS As UdpClient
        Dim AnyEPAs IPEndPoint
        Dim btyRecv As Byte()
        Dim btySend As Byte()
        Declare Function timeGetTime Lib "winmm.dll" () As Long

        Dim EP As IPEndPoint
        Dim B As Byte() = Encoding.ASCII.GetBytes("XXXXXXXXXXXXXXXXXXXXXXX")

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            UDPL = New UdpClient()
            Dim tm11 As Long
            UDPL.EnableBroadcast = True


            EP = New IPEndPoint(IPAddress.Parse("255.255.255.255"), 6990)
            AnyEP = New IPEndPoint(IPAddress.Any, 0)
            UDPL.Send(B, B.Length, EP)

            btySend = Encoding.ASCII.GetBytes(Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString)
           
            Dim i As Integer = 0, a As String = ""


            tm11 = timeGetTime()
            Do
                Application.DoEvents()
            Loop Until UDPL.Available > 0 Or timeGetTime() - tm11 >= 10000

            If UDPL.Available > 0 Then
                btyRecv = UDPL.Receive(AnyEP)
                'ListBox1.Items.Add(Encoding.ASCII.GetString(btyRecv, 0, btyRecv.Length))
                For i = 0 To UBound(btyRecv)
                    If i >= 0 And i <= 19 Then
                        a &= Chr(btyRecv(i))
                    ElseIf i >= 20 And i <= 23 Then
                        a &= Val(btyRecv(i))
                    ElseIf i >= 24 And i <= 29 Then
                        a &= Microsoft.VisualBasic.Right("00" & Hex(btyRecv(i)), 2)
                    Else
                        a &= Chr(btyRecv(i))
                    End If
                Next
                ListBox1.Items.Add(a)
            End If

        End Sub

    End Class

     

    不過其中有一行 有點問題

    btySend = Encoding.ASCII.GetBytes(Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString)
    不太了解這行的意義

     

    還有 都只能收到一台

    網路上如果有兩台以上

    只會收到

    第一台回應的

    這又要如何解決呢?

    再次麻煩各位大大了

    2008年4月7日 上午 01:58
  • Encoding.ASCII.GetBytes(Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString) 這行拆開來看,Encoding.ASCII.GetBytes是將一串ASCII的"字串"轉換為Byte陣列,而Dns.GetHostByName....那一段是取得本機的IP位址(要注意的是這段在Vista會有問題)。

    而只收到一台是因為你只收取一次資料,你可以先用TImer控制項去做,把接收、處理資料的部分放在Timer裡面做,這樣測試看看。

    2008年4月7日 上午 03:15
    版主
  • 謝謝 大大了

    該行在我的VB.NET中

    會顯示一項 警告

    警告 1 'Public Shared Function GetHostByName(hostName As String) As System.Net.IPHostEntry' 已經過時: 'GetHostByName is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202' 

    它的說明就是看不太懂><"

     

    我後來 直接使用 DO LOOP迴圈 我廣播後 該項回應 會在 一分鐘內 回應我

    這樣就OK了 全部的機器都有回應回來了

    我沒有使用TIMER 在VB6中 它就很不穩定了

     

    廣播後 其實我除了等待

    還有不少個FUNCTION 再跑

     

    再次謝謝 大大的幫忙唷

    我真的很想搞懂   "已經過時" <===這是什麼意義

     

    2008年4月7日 上午 03:42
  • 已經過時的意思是說,這個"方法"是舊版的,已經有提供新的"方法"可以呼叫,因為我懶惰..沒有去修正..

    "已經過時"同時也表示將來新的版本不一定會有這個"方法"可以呼叫,有可能會拿掉的意思。

     

    另外,如果你不想用Timer的話,在Do...Loop的迴圈裡面除了 Doevents之外最好加上Threading.Sleep來放出CPU時間,不然在Do...Loop那段時間CPU會滿載

    2008年4月7日 上午 04:56
    版主
  • 那就再次謝謝大大了

    感恩

    這次真的有學到很多東西

    ^^

    2008年4月7日 上午 05:00