Có nhiều câu hỏi ở đây rất giống nhau, không có câu trả lời nào được cung cấp đã giúp tôi, điều này khiến tôi buồn: (UDP SocketException - Chỉ có một cách sử dụng của mỗi địa chỉ socket thường được cho phép
I đã có một hệ thống quản lý rất lớn mà tôi đã được giao nhiệm vụ viết một số gói tin gửi/nhận UDP. Tôi đã viết một mẫu thử nghiệm và tất cả đều tốt, vì vậy tôi bắt đầu hợp nhất mã của tôi vào hệ thống đã nói. bây giờ đã có một SocketException (không hiển thị, nhưng gây phiền nhiễu) xuất hiện:
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
Đây là lớp UDPReceiver - có trách nhiệm chỉ ngồi trong một vòng lặp và chờ phản hồi từ các Máy chủ thiết bị mà chúng tôi đã tìm hiểu về địa điểm.
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
Bây giờ, tất cả tôi đang làm theo hình thức chính, đó là: Khi hình thức người nghe của tôi bị đóng - Tôi muốn đóng listener xuống (rõ ràng) ... Đối với điều này, tôi đang sử dụng Dispose()
. Tuy nhiên, khi ai đó muốn khởi động lại nó, ngoại lệ nói trên xảy ra trên đường dây byData = _ReceivingClient.Receive(epEndPoint)
trong thủ tục SitAndReceive
.
Vì UDP dựa trên giao dịch và các ổ cắm của nó (có thể về mặt lý thuyết) không thể ở trạng thái CLOSE_WAIT, điều gì ngăn tôi đóng nó lại và sau đó khởi chạy lại trình lắng nghe ngay lập tức?
Tôi phải thừa nhận mình là người mới sử dụng ổ cắm UDP, tuy nhiên, tôi thấy họ rất vui khi làm việc và mặc dù ngoại lệ này sẽ không làm hỏng phần mềm người dùng cuối (với thử/nắm bắt đơn giản), nó làm tôi tò mò và tôi muốn hiểu tại sao nó lại xảy ra.
Bất kỳ trợ giúp nào được đánh giá rất nhiều.
Tuyệt vời! Tôi có những vấn đề giống nhau. Tôi đã mất một lúc để tìm ra lý do tại sao nó không hoạt động và tôi nhận ra rằng tôi đang khởi tạo đối tượng UdpClient của mình với một cổng (như '_receiver = new UdpClient (myPort)'), mà phải làm một số ràng buộc cơ bản. Sau khi tôi sử dụng constructor mặc định, nó hoạt động tốt. – Daniel
Đẹp nhất :) Vui vì bạn đã làm việc đó! – LokiSinclair
Giải pháp của bạn hoạt động tốt! Tôi đã gửi một yêu cầu đa hướng, có nhiều người nhận trên cùng một máy chủ. Tôi đã nhận được cùng một lỗi khi tôi đã cố gắng để chạy nhiều hơn một máy thu mà phải lắng nghe cùng một cổng. –