2013-07-22 31 views
5

至於因爲有在這裏是非常相似的,沒有提供答案,幫助我,這讓我傷心:(UDP SocketException - 每個套接字地址通常是允許的一個用法

我很多問題多我有一個非常大的管理系統,我負責編寫一些UDP數據包發送/接收服務,我已經寫了一個原型,一切都很好,所以我開始將我的代碼合併到上述系統中,但是,現在已經有一個(不是表演停止,但是很煩)SocketException彈出:

System.Net.Sockets.SocketException occurred 
    ErrorCode=10048 
    Message=Only one usage of each socket address (protocol/network address/port) is normally permitted 
    NativeErrorCode=10048 
    Source=System 
    StackTrace: 
     at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress) 
     at System.Net.Sockets.Socket.Bind(EndPoint localEP) 
     at System.Net.Sockets.UdpClient..ctor(Int32 port, AddressFamily family) 
     at System.Net.Sockets.UdpClient..ctor(Int32 port) 
     at Goose.Job.DeviceServerUDPReceiver.InitialiseReceiverClient() in C:\WORK\Trunk\GooseOrders\Classes\SheetCounter\DeviceServerUDPReceiver.vb:line 39 

這裏是UDPReceiver類 - 這是負責只是坐在一個循環並等待我們在這個地方散佈的設備服務器的響應。

Public Class DeviceServerUDPReceiver : Implements IDisposable 
'/////////////////////////////////////////////////////////////////////////////// 
' CONSTANTS 
'/////////////////////////////////////////////////////////////////////////////// 
Private Const TIBBO_DEVICE_REPLY_CMD_START As Integer = 0 
Private Const TIBBO_DEVICE_REPLY_CMD_END As Integer = 3 
Private Const TIBBO_MESSAGE_REPLY_DIVIDER As String = "_" 
Private Const TIBBO_DEVICE_REPLY_OK As String = "OK" 

'/////////////////////////////////////////////////////////////////////////////// 
' MEMBER VARIABLES 
'/////////////////////////////////////////////////////////////////////////////// 
Public _ReceivingClient As System.Net.Sockets.UdpClient 
Public _iReceivingPort As Integer = 2002 
Public _thReceivingThread As System.Threading.Thread 
Public _bClosing As Boolean 

'/////////////////////////////////////////////////////////////////////////////// 
' EVENTS 
'/////////////////////////////////////////////////////////////////////////////// 
Public Event GotDeviceResponse(ByVal sResponse As String) 
Public Event FoundNewDevice(ByVal TibboObject As TibboDevice) 

'/////////////////////////////////////////////////////////////////////////////// 
' METHODS 
'/////////////////////////////////////////////////////////////////////////////// 
' Initialises the UDP receiver client on the specified port number. Then runs 
' a listening thread constantly waiting to receive udp messages 
Public Sub InitialiseReceiverClient() 
    Try 
     ' TODO - FIX SOCKET EXCEPTION HERE - NOT THREAD ISSUE - THIS IS DUE TO 
     ' THE SOCKET NOT BEING CLOSED. BUT SEEING HOW UDP IS CONNECTIONLESS .... ?! 
     _ReceivingClient = New System.Net.Sockets.UdpClient(_iReceivingPort) 
     Dim thStartThread As Threading.ThreadStart = New Threading.ThreadStart(AddressOf SitAndReceive) 
     _thReceivingThread = New Threading.Thread(thStartThread) 
     _thReceivingThread.IsBackground = True 
     _thReceivingThread.Start() 
    Catch ex As System.Net.Sockets.SocketException 
     Console.WriteLine("Socket Exception: " & ex.Message) 
    Finally 

    End Try 
End Sub 

' The endless loop listener thread. Will sit and wait for udp packets to 
' process 
Private Sub SitAndReceive() 
    Dim epEndPoint As System.Net.IPEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, _iReceivingPort) 

    ' infinite loop to listen for udp messages 
    While (_bClosing = False) 
     Try 
      Dim sMessage As String = "" 
      Dim byData() As Byte 

      byData = _ReceivingClient.Receive(epEndPoint) 
      sMessage = System.Text.Encoding.ASCII.GetString(byData) 
      Console.WriteLine(sMessage) 

      ProcessIncomingUDPDataMessage(sMessage) 

     Catch ex As System.Net.Sockets.SocketException 
      Console.WriteLine(ex.Message) 
     End Try 
    End While 
End Sub 

' close the connection to the receiving udp socket 
Public Sub Close() 
    _bClosing = True 
End Sub 


' Processes incoming udp packets for answeres from the device servers 
Private Sub ProcessIncomingUDPDataMessage(ByVal sMessage As String) 

    ' UDP Data packet from Tibbo devices is set out as follows 
    ' 
    ' CMD_ANSWER 
    ' Where "CMD" = The command the device is replying too and 
    ' "ANSWER" = It's reply 
    Select Case sMessage.Substring(TIBBO_DEVICE_REPLY_CMD_START, TIBBO_DEVICE_REPLY_CMD_END) 
     Case TibboDevice.DEVICE_COMMAND_ATO 
      '///////////////////////////////////////////////////////////////////////// 
      ' Any Tibbo's out there reply message 
      '///////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sMacAddress As String = s(2) ' the replying devices' mac address 
      Dim sIpAddress As System.Net.IPAddress = System.Net.IPAddress.Parse(s(3)) ' ip 
      Dim sNetBiosName As String = s(1) ' netbios name 
      Dim iTibboStatus As TibboDevice.ETIIBO_DEVICE_STATE = TibboDevice.ETIIBO_DEVICE_STATE.TIBBO_DEVICE_STATE_BAD ' status 

      ' set this device status depending on the reply 
      If s(4) = TIBBO_DEVICE_REPLY_OK Then 
       iTibboStatus = TibboDevice.ETIIBO_DEVICE_STATE.TIBBO_DEVICE_STATE_OK 
      End If 

      ' create a new tibbo device to pass back to the main form 
      Dim Tibbo As TibboDevice = New TibboDevice(sMacAddress, sIpAddress, sNetBiosName, iTibboStatus) 
      ' raise event to add this to our list 
      RaiseEvent FoundNewDevice(Tibbo) 


     Case TibboDevice.DEVICE_COMMAND_STS 
      '////////////////////////////////////////////////////////////////////////// 
      ' Status reply message 
      '////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      ' format our string nicely 
      sResult &= "Mac Address: " & vbTab & vbTab & s(1) 
      sResult &= Environment.NewLine & "IP Address: " & vbTab & vbTab & s(2) 
      sResult &= Environment.NewLine & "Device Name: " & vbTab & vbTab & s(3) 
      sResult &= Environment.NewLine & "TiOS FW: " & vbTab & vbTab & s(4) 
      sResult &= Environment.NewLine & "Goose SC FW: " & vbTab & vbTab & s(5) 
      sResult &= Environment.NewLine & "System Uptime: " & vbTab & vbTab & s(6) 
      sResult &= Environment.NewLine & "System Time: " & vbTab & vbTab & s(7) 
      sResult &= Environment.NewLine & "System Status: " & vbTab & vbTab & s(8) 

      RaiseEvent GotDeviceResponse(sResult) 

     Case TibboDevice.DEVICE_COMMAND_ASC 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Average sheet count message 
      '//////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      RaiseEvent GotDeviceResponse(sResult) 

     Case TibboDevice.DEVICE_COMMAND_NAM 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Changed device name reply message 
      ' Device will reply NAM_[NEWNAME] - once it's set it's new name 
      '//////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      RaiseEvent GotDeviceResponse(sResult) 

     Case TibboDevice.DEVICE_COMMAND_IDX 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device responds with it's device id 
      '//////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      ' TODO - do something with the result 

     Case TibboDevice.DEVICE_COMMAND_RBT 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device is going down for a reboot - not much to do here, we have to wait 
      '//////////////////////////////////////////////////////////////////////////// 

     Case TibboDevice.DEVICE_COMMAND_BUZ 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device has played it's buzz sound - ignore 
      '//////////////////////////////////////////////////////////////////////////// 

     Case TibboDevice.DEVICE_COMMAND_FSH 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device flashed it's LEDs - ignore 
      '//////////////////////////////////////////////////////////////////////////// 

     Case TibboDevice.DEVICE_COMMAND_AIP 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device replies with it's actual ip address 
      '//////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      ' TODO - do something with the result 

     Case TibboDevice.DEVICE_COMMAND_CBC 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device replies with it's current box count 
      '//////////////////////////////////////////////////////////////////////////// 
      Dim s() As String = sMessage.Split(TIBBO_MESSAGE_REPLY_DIVIDER) 
      Dim sResult As String = "" 

      ' TODO - do something with the result 

     Case TibboDevice.DEVICE_COMMAND_STP 
      '//////////////////////////////////////////////////////////////////////////// 
      ' Device has been stopped - won't reply. Only way to bring it back to life 
      ' is to press the 'reset' button on the actual unit - ignore 
      '//////////////////////////////////////////////////////////////////////////// 
    End Select 

End Sub 

Protected Overridable Overloads Sub Dispose(disposing As Boolean) 
    If (disposing) Then 
     ' free managed objects 
     '_ReceivingClient = Nothing 
     _bClosing = True 
    End If 
End Sub 

Public Overloads Sub Dispose() Implements IDisposable.Dispose 
    Dispose(True) 
    GC.SuppressFinalize(Me) 
End Sub 


End Class 

現在,所有我做的主要形式,是:當我的聽衆窗體關閉 - 我想關閉監聽下降(顯然)......對於這一點,我使用Dispose()。但是,當有人想再次啓動它時,在SitAndReceive過程的byData = _ReceivingClient.Receive(epEndPoint)行中發生異常。

由於UDP基於事務,並且其套接字(理論上可能不能處於CLOSE_WAIT狀態),什麼阻止我關閉它,然後立即重新啓動偵聽器?

我必須承認我是UDP套接字的新手,但迄今爲止,我發現他們很高興與之合作,即使此異常不會使最終用戶軟件崩潰(通過簡單的try/catch ),它確實讓我感興趣,我想了解它爲什麼會發生。

任何幫助,非常感謝。

回答

14

終於搞清楚了。很顯然,如果你想有一個以上的連接插座,您必須手動配置它,就像這樣:

Dim endPoint = New System.Net.IPEndPoint(0, _iReceivingPort) 
_ReceivingClient = New System.Net.Sockets.UdpClient() 
_ReceivingClient.ExclusiveAddressUse = False 
_ReceivingClient.Client.SetSocketOption(Net.Sockets.SocketOptionLevel.Socket, Net.Sockets.SocketOptionName.ReuseAddress, True) 
_ReceivingClient.Client.Bind(endPoint) 

現在的作品,所以我很高興。

+1

不錯!我遇到了同樣的問題。我花了一段時間才弄清楚它爲什麼沒有工作,我意識到我正在用一個端口實例化我的UdpClient對象(比如'_receiver = new UdpClient(myPort)'),它必須做一些底層綁定。在我使用默認構造函數後,它工作正常。 – Daniel

+0

不錯的一個:)很高興你的工作! – LokiSinclair

+0

你的解決方案工作得很好!我正在發送多播請求,在同一主機上有多個接收器。當我試圖運行多個不得不聽同一端口的接收器時,我遇到了同樣的錯誤。 –

相關問題