Why? I have a AV Media Server that follows the UPnP 1.0 Spec. that needs to be accessed from an Xbox 360 UPnP Rendering Device which is connected to the LAN via MS's ICS which routes data to and from the device. This creates a (seperate subnet/broadcast domain) therfore when the Xbox sends a SSDP discovery broadcast to discover the Media Server, if the server receives/responds, the return broadcast won't be received. From what I understand TCP/IP was intentionally designed to prevent broadcasts from being routed to other LANs. This creates a problem when you have a second broadcast domain on your primary LAN. Essentially, I have a WAN if you disregard the distances.
Still making a lot of assumptions here, If I receive the broadcast from the Media Server on the Comp. that is connected directly to the network aka the same broadcast domain, which provides the Xbox with Internet connectivity then relaying that broadcast from its neutral location would successfully allow the Xbox to discover the Media Server, as the Location header field(has the address of the server) in the relayed broadcast will reveal the information needed for the Xbox to become a control point of the Media Server.
I would love some clarifications on the subject. I need to be able to receive multicast SSDP discovery messages via UDP. I've tried and failed so far... I can send a UPnP service discovery broadcast and receive respones but when I try to listen for these broadcasts, I fail.
I've attempted to bind to the multicast address - 239.255.255.255 on port 1900 and @IPAddress1 on an available high number port without luck. I really don't know much, just what I've read.
Thanks Everyone.
Edit - I can bind to the address mentioned above, I just don't receive any data. My best quess is that I'm not listening properly!!!
I'm using this script to send a UPnP SSDP Broadcast.
#include <Array.au3> #include <Inet.au3> #include <String.au3> #include <Icons.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> ;#include <_XMLDomWrapper.au3> ; -- SSDP Discovery via UPnP -- Global $sErrMsg = "SSDP Discovery Failed!" & @CRLF & @CRLF, $iErrorSuccess = 0 Global $aRecycleBin_InitialSize = 25, $aRecycleBin[$aRecycleBin_InitialSize] ; ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; SSDP Broadcast: ; Recieve and Send Sockets are the same and use the same variable --- $aSocket. ; Tested on XP. Works on Win 7 only when all but one NIC have been disabled via the device manager. ; ; SSDP Discovery Error Codes: ; 1 = UDP Open Error ; 2 = UDP Send Error ; 3 = UDP Recv Error ; 4 = UDP Bind Error ; ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Global $aResponse ; Empty variables for data collection Global $iResult = SSDP_Broadcast($aResponse) Switch @error Case 1 $sErrMsg &= "UDP Open Error" Case 2 $sErrMsg &= "UDP Send Error" Case 3 $sErrMsg &= "UDP Recv Error" Case 4 $sErrMsg &= "UDP Bind Error" Case Else $sErrMsg = False EndSwitch If $sErrMsg Then MsgBox(16 + 262144, "SSDP Discovery:", $sErrMsg) Exit EndIf If $iResult Then Global $aDevice[$aResponse[0] + 1][15] $aDevice[0][0] = $aResponse[0] ; Global Enum Identifiers 0 - 14 = 15 elements Global Enum $iLOCATION, $iEXT, $iUSN, $iSERVER, $iCACHECONTROL, $iST, $iDATE, $iCONTENTLENGTH, $iIP, $iXML, $iRESPONSE, _ $iFRIENDLYNAME, $iDEVICETYPE, $iICONURL, $iMODELNAME For $i = 1 To $aDevice[0][0] Step 1 $aDevice[$i][$iRESPONSE] = $aResponse[$i] Next _ParseResponse() EndIf Global $aTemp[$aDevice[0][0] + 1][15], $iCount = 0, $iD, $bMatch = False For $i = 1 To $aDevice[0][0] Step 1 If $aDevice[$i][$iLOCATION] <> "" Then $bMatch = False For $iD = 1 To $aDevice[0][0] Step 1 If $aDevice[$i][$iSERVER] = $aTemp[$iD][$iSERVER] And _ $aDevice[$i][$iLOCATION] = $aTemp[$iD][$iLOCATION] Then $bMatch = True If $aDevice[$i][$iLOCATION] = $aTemp[$iD][$iLOCATION] And $aDevice[$i][$iUSN] <> "" Then If $aTemp[$iD][$iUSN] = "" Then $aTemp[$iD][$iUSN] = $aDevice[$i][$iUSN] EndIf EndIf EndIf Next If $bMatch Then ContinueLoop Else $iCount += 1 $aTemp[$iCount][$iLOCATION] = $aDevice[$i][$iLOCATION] $aTemp[$iCount][$iEXT] = $aDevice[$i][$iEXT] $aTemp[$iCount][$iSERVER] = $aDevice[$i][$iSERVER] $aTemp[$iCount][$iCACHECONTROL] = $aDevice[$i][$iCACHECONTROL] $aTemp[$iCount][$iST] = $aDevice[$i][$iST] $aTemp[$iCount][$iUSN] = $aDevice[$i][$iUSN] $aTemp[$iCount][$iDATE] = $aDevice[$i][$iDATE] $aTemp[$iCount][$iCONTENTLENGTH] = $aDevice[$i][$iCONTENTLENGTH] $aTemp[$iCount][$iIP] = _ExtractIP($aDevice[$i][$iLOCATION]) $aTemp[$iCount][$iRESPONSE] = $aDevice[$i][$iRESPONSE] EndIf EndIf Next If $iCount Then $aTemp[0][0] = $iCount $aDevice = $aTemp $aTemp = "" ReDim $aDevice[$iCount + 1][15] EndIf For $i = 1 To $aDevice[0][0] Step 1 $aDevice[$i][$iXML] = _INetGetSource($aDevice[$i][$iLOCATION]) $hXML = FileOpen($aDevice[$i][$iIP] & " - Location" & $i & ".xml", 2) FileWrite($hXML, $aDevice[$i][$iXML]) FileClose($hXML) $aDevice[$i][$iXML] = $aDevice[$i][$iIP] & " - Location" & $i & ".xml" _RecycleBin($aDevice[$i][$iXML]) Next Dim $aType, $sXML, $sIcon, $hPic, $sImage, $sFriendlyName, $sMsg, $sIconURL Dim $hBroadcastButton, $hCancelButton For $iDEV = 1 To $aDevice[0][0] Step 1 $sXML = FileRead($aDevice[$iDEV][$iXML]) $aType = _StringBetween($sXML, "<deviceType>", "</deviceType>") If IsArray($aType) Then $aDevice[$iDEV][$iDEVICETYPE] = $aType[0] ConsoleWrite(">Found " & $aDevice[$iDEV][$iDEVICETYPE] & " at " & $aDevice[$iDEV][$iLOCATION] & @CRLF) GUICreate("UPnP Device", 300, 100, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW)) $aDevice[$iDEV][$iMODELNAME] = _GetModelName($sXML) $iSolidus = StringInStr($aDevice[$iDEV][$iLOCATION], "/", 2, 3) $sIcon = StringMid($aDevice[$iDEV][$iLOCATION], 1, $iSolidus - 1) If Not @error Then $sIconURL = _GetIcon32($sXML) $sIcon &= $sIconURL $sImage = @ScriptDir & "\Device.png" If $sIconURL <> "" Then InetGet($sIcon, $sImage, 1) Else If $aDevice[$iDEV][$iMODELNAME] = "Xbox 360" Then $sImage = @ScriptDir & "\Xbox360black.png" Else $sImage = @ScriptDir & "\Question.png" EndIf EndIf $aDevice[$iDEV][$iICONURL] = $sImage $hPic = GUICtrlCreatePic("", 10, 20, 32, 32) _SetImage($hPic, $sImage) $sFriendlyName = _StringBetween($sXML, "<friendlyName>", "</friendlyName>") If IsArray($sFriendlyName) Then $sFriendlyName = _ArrayToString($sFriendlyName, "") $aDevice[$iDEV][$iFRIENDLYNAME] = $sFriendlyName ConsoleWrite($aDevice[$iDEV][$iFRIENDLYNAME] & @CRLF) GUICtrlCreateLabel($aDevice[$iDEV][$iFRIENDLYNAME], 52, 28, 248, 15) EndIf $hBroadcastButton = GUICtrlCreateButton("&Relay this broadcast", 55, 72, 145, 22) $hCancelButton = GUICtrlCreateButton("&Cancel", 210, 72, 80, 22) EndIf GUISetState() While 1 $sMsg = GUIGetMsg() Switch $sMsg Case $GUI_EVENT_CLOSE ExitLoop Case $hBroadcastButton GUIDelete() _RelayBroadcast($iDEV) Case $hCancelButton ExitLoop EndSwitch WEnd GUIDelete() EndIf Next Func _Exit() _RecycleBin("", True) Exit(0) EndFunc Func _RelayBroadcast($iDEV) ;Global Enum $iLOCATION, $iEXT, $iUSN, $iSERVER, $iCACHECONTROL, $iST, $iDATE, $iCONTENTLENGTH, $iIP, $iXML, $iRESPONSE, _ ; $iFRIENDLYNAME, $iDEVICETYPE, $iICONURL, $iMODELNAME UDPStartup() Local $aSocket = UDPOpen("239.255.255.250", 1900) Local Enum $iSocket = 0, $iAddress = 1, $iPort = 2 If Not $aSocket[$iSocket] Then Return SetError(1, 0, 0) ; Failed to open socket. EndIf HotKeySet("{ESC}", "_Exit") While 1 TrayTip("UPnP Relay - " & $aDevice[$iDEV][$iFRIENDLYNAME], "+>Broadcasting..." & @CRLF & @CRLF & $aDevice[$iDEV][$iRESPONSE] & @CRLF & @CRLF, 2) UDPSend($aSocket, StringReplace($aDevice[$iDEV][$iRESPONSE], "TVersity Media Server", "UPnP Relay")) Sleep(1000) WEnd UDPCloseSocket($aSocket) UDPShutdown() _Exit() EndFunc Func _GetModelName($sXML) Local $aModel = _StringBetween($sXML, "<modelName>", "</modelName>") If IsArray($aModel) Then Return $aModel[0] EndIf EndFunc ;==>_GetModelName Func _GetIcon32($sXML) Local $aIconList = _StringBetween($sXML, "<iconList>", "</iconList>") If IsArray($aIconList) Then Local $aIcon = _StringBetween($aIconList[0], "<icon>", "</icon>"), $aURL, $aSize If IsArray($aIcon) Then For $i = 0 To UBound($aIcon, 1) - 1 Step 1 $aSize = _StringBetween($aIcon[$i], "<width>", "</width>") If IsArray($aSize) Then If $aSize[0] = "32" Then $aURL = _StringBetween($aIcon[$i], "<url>", "</url>") If IsArray($aURL) Then Return $aURL[0] EndIf EndIf EndIf Next EndIf EndIf EndFunc ;==>_GetIcon32 Func _ParseResponse() For $iDEV = 1 To $aDevice[0][0] Step 1 Local $aLine = StringSplit($aDevice[$iDEV][$iRESPONSE], @CRLF, 1), $iColon, $aData[2] For $i = 1 To $aLine[0] Step 1 $iColon = StringInStr($aLine[$i], ":", 2, 1) If $iColon Then $aData[0] = StringStripWS(StringMid($aLine[$i], 1, $iColon - 1), 3) $aData[1] = StringStripWS(StringMid($aLine[$i], $iColon + 1, StringLen($aLine[$i]) - $iColon), 3) Switch $aData[0] Case "LOCATION" $aDevice[$iDEV][$iLOCATION] = $aData[1] Case "EXT" $aDevice[$iDEV][$iEXT] = $aData[1] Case "USN" $aDevice[$iDEV][$iUSN] = $aData[1] Case "SERVER" $aDevice[$iDEV][$iSERVER] = $aData[1] Case "CACHE-CONTROL" $aDevice[$iDEV][$iCACHECONTROL] = $aData[1] Case "ST" $aDevice[$iDEV][$iST] = $aData[1] Case "DATE" $aDevice[$iDEV][$iDATE] = $aData[1] Case "CONTENT-LENGTH" $aDevice[$iDEV][$iCONTENTLENGTH] = $aData[1] EndSwitch EndIf Next Next EndFunc ;==>_ParseResponse Func SSDP_Broadcast(ByRef $aResponse) Local $iSearchTime = 15000, $iSendInterval = 3000 ; Values are in miliseconds Local $iLastTimeCheck, $iTimeLeft Local $iSendCounter = 0, $iResponseCounter = 0 Local $sResponse, $sIP Local $iRValue = 1, $iFuncError = 0 Local Const $sBroadcast = _ 'M-SEARCH * HTTP/1.1' & @CRLF & _ 'ST:upnp:rootdevice' & @CRLF & _ 'MX: 10' & @CRLF & _ 'MAN: "ssdp:discover"' & @CRLF & _ 'HOST: 239.255.255.250:1900' & @CRLF & _ @CRLF UDPStartup() Local $aSocket = UDPOpen("239.255.255.250", 1900) Local Enum $iSocket = 0, $iAddress = 1, $iPort = 2 ; _ArrayDisplay($aSocket) If Not $aSocket[$iSocket] Then Return SetError(1, 0, 0) ; Failed to open socket. EndIf ; Start the Search Timer Local $hSearchTime = TimerInit(), $hSendTime = "" ; Variables to store the time difference from when the timer initialized. Local $iSearchTimer, $iSendTimer ; $iSendTimer hasn't been initialized so increase the value so that $iSendTimer is greater than $iSendInterval which prevents an inital delay. Local $iSendTimer = ($iSendInterval + 1) While 1 ; Send the first message immediately, afterwards, Send at the specified interval, which is stored in $iSendInterval If $iSendCounter Then $iSendTimer = TimerDiff($hSendTime) EndIf ; SSDP Broadcast If $iSendTimer > $iSendInterval Then $iSendCounter += 1 UDPSend($aSocket, $sBroadcast) If @error <> $iErrorSuccess Then $iFuncError = 2 ; Local Function - Error Code $iRValue = $iErrorSuccess ExitLoop EndIf ConsoleWrite(">SSDP Broadcast #" & $iSendCounter & @CRLF & @CRLF) ; Reinitialize the Send Timer $hSendTime = TimerInit() EndIf ; Short Pause (after the Send) Sleep(100) ; Recieve Response $sResponse = UDPRecv($aSocket, 1024) If @error <> 0 Then $iFuncError = 3 ; Local Function - Error Code $iRValue = 0 ExitLoop EndIf If $sResponse <> "" Then ; If the response isn't null then execute this block $iResponseCounter += 1 ConsoleWrite("-------------------- Received Response #" & $iResponseCounter & " --------------------" & @CRLF) ConsoleWrite($sResponse & @CRLF) ; If the Response isn't null and isn't already in array then add it. _AddToArray($aResponse, $sResponse, True) EndIf ; Update the Search Timer $iSearchTimer = TimerDiff($hSearchTime) ; If the deadline is met or past due then exit the While-Wend loop. If $iSearchTimer >= $iSearchTime Then ExitLoop Else ; Calculate and display the remaing time $iTimeLeft = Ceiling(($iSearchTime - $iSearchTimer) / 1000) If $iTimeLeft <> $iLastTimeCheck Then TrayTip("SSDP-Discovery", "Searching for devices via UPnP (" & $iTimeLeft & " seconds) remaining... ", 5, 1) $iLastTimeCheck = $iTimeLeft EndIf EndIf WEnd TrayTip("", "", 0) ; close the TrayTip UDPCloseSocket($aSocket) UDPShutdown() ; Sort the arrays If IsArray($aResponse) Then _ArraySort($aResponse, 0, 1) If $iFuncError Then ; If there was an error then set the @error macro and return $iRValue Return SetError($iFuncError, 0, $iRValue) Else Return $iRValue EndIf EndFunc ;==>SSDP_Broadcast Func _ExtractIP($sResponse) Local $vIP = StringRegExp($sResponse, "\d+\.\d+\.\d+\.\d+", 1) ; The regular expression above should return an array. If Not IsArray($vIP) Then Return EndIf ; The first index should contain the IP address. $vIP = $vIP[0] ; Ensure that the address is IPv4. If _IsIPv4($vIP) Then Return $vIP EndIf EndFunc ;==>_ExtractIP Func _IsIPv4($sIP) If StringRegExp($sIP, "\A(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])\z") Then Return True EndIf EndFunc ;==>_IsIPv4 Func _AddToArray(ByRef $avArray, $vData, $bOnlyAddUnique = False) If IsArray($avArray) Then If $bOnlyAddUnique Then ; _ArraySeach(Array, Value, Starting Index) - Function Definition If _ArraySearch($avArray, $vData, 1, 0, 1, 0, 0, 1) <> -1 Then ; If the value already exists than return Return False EndIf EndIf Local $iRValue = _ArrayAdd($avArray, $vData) If $iRValue <> -1 Then ; Increase and return the index counter. $avArray[0] += 1 Return $avArray[0] Else Return $iRValue EndIf Else ; Create the array Dim $avArray[2] $avArray[0] = 1 $avArray[1] = $vData Return True EndIf EndFunc ;==>_AddToArray Func _RecycleBin($sFileName = "", $bCommit = False) Static Local $iFile = 0 Local $iUbound = UBound($aRecycleBin, 1) If $iFile >= $iUbound Then ReDim $aRecycleBin[$iUbound + $aRecycleBin_InitialSize] EndIf If $bCommit Then For $iFile = 0 To UBound($aRecycleBin, 1) - 1 FileDelete($aRecycleBin[$iFile]) $aRecycleBin[$iFile] = "" Next ReDim $aRecycleBin[$aRecycleBin_InitialSize] Return 1 EndIf $aRecycleBin[$iFile] = $sFileName $iFile += 1 Return 1 EndFunc ;==>_RecycleBin #cs ; Function that performs a UPnP ssdp-discover and writes the results into an array. ; In addition, the IP addresses of the devices are written in a second array. ; V2: Receive-Socket and Send-Socket are differ. I try many different ways, but nothing works :-( ; SSDP Discovery: ; 0 = kein Error ; 1 = UDPOpen-error ; 2 = UDPSend-error ; 3 = UDPRecv-error ; 4 = UDPBind-error Func SSDPdiscover_V2(ByRef $aResponse, ByRef $aIP, $iSearchTime = 10000, $iSendInterval = 1000) ; --- UPnP-Kommando --- Local Const $sBroadcast = _ 'M-SEARCH * HTTP/1.1' & @CRLF & _ 'ST:upnp:rootdevice' & @CRLF & _ 'MX: 10' & @CRLF & _ 'MAN: "ssdp:discover"' & @CRLF & _ 'HOST: 239.255.255.250:1900' & @CRLF & _ @CRLF Local $aSocket, $aSocket Local $iSendCounter = 0, $iResponseCounter = 0 Local $sResponse, $sIP Local $hSearchTime, $iSearchTimer ; Timeout-Timer Local $hSendTime, $iSendTimer ; Send-Timer Local $iLastTimeCheck = -99, $iTimeLeft Local $iRValue = 1, $iFuncError= 0 ; Arrays "löschen" $aResponse = "" $aIP = "" ; UPnP-Kommando ausgeben ConsoleWrite(@CRLF) ConsoleWrite("UPnP-Kommando:" & @CRLF) ConsoleWrite($sBroadcast & @CRLF) ; UDP starten UDPStartup() ; - Sender - ; $array[1] contains the real socket, $array[2] contains the specified IP address and $array[3] contains the port $aSocket = UDPOpen("239.255.255.250", 1900) ConsoleWrite("SendSocket: real socket: " & $aSocket[1] & ", IP-address: " & $aSocket[2] & ", port: " & $aSocket[3] & @CRLF & @CRLF) ; _ArrayDisplay($aSocket) If $aSocket[0] == -1 Or $aSocket[0] == 0 Then ; documentation is somewhat vague ; Error 1 Return SetError(1, 0, 0) EndIf ; - Empfänger - If @IPAddress1 <> "0.0.0.0" Then ConsoleWrite(@IPAddress1 & @CRLF) If @IPAddress2 <> "0.0.0.0" Then ConsoleWrite(@IPAddress2 & @CRLF) If @IPAddress3 <> "0.0.0.0" Then ConsoleWrite(@IPAddress3 & @CRLF) If @IPAddress4 <> "0.0.0.0" Then ConsoleWrite(@IPAddress4 & @CRLF) ; $aSocket = UDPBind("127.0.0.1", 1900) ; $aSocket = UDPBind(@IPAddress1, 1900) ; $aSocket = UDPBind("127.0.0.1", $aSocket[1]) ; $aSocket = UDPBind(@IPAddress1, $aSocket[1]) ; $aSocket = UDPBind("239.255.255.250", 1900) $aSocket = UDPBind(@IPAddress1, 1900) ConsoleWrite("ReceiveSocket: real socket: " & $aSocket[1] & ", IP-address: " & $aSocket[2] & ", port: " & $aSocket[3] & @CRLF & @CRLF) ; _ArrayDisplay($aSocket) If $aSocket[0] == -1 Or $aSocket[0] == -0 Then ; documentation is somewhat vague ; Error 4 Return SetError(4, 0, 0) EndIf ; Timer setzen $hSearchTime = TimerInit() ; Timeout-Timer $hSendTime = -99 ; temporary solution, could be better :) While 1 ; SenderPause calculate If $hSendTime = -99 Then ; Timer has not been set, so put ticks Used $iSendTimer = $iSendInterval + 10 Else ; calculate $iSendTimer = TimerDiff($hSendTime) EndIf ; Send If $iSendTimer > $iSendInterval Then $iSendCounter += 1 ConsoleWrite("UPnP Send Count No. " & $iSendCounter & @CRLF & @CRLF) UDPSend($aSocket, $sBroadcast) If @error <> 0 Then $iFuncError= 2 $iRValue = 0 ExitLoop EndIf ; reset timer $hSendTime = TimerInit() EndIf ; Short Pause (after the Send) Sleep(100) ; Recieve $sResponse = UDPRecv($aSocket, 1024) If @error <> 0 Then $iFuncError= 3 $iRValue = 0 ExitLoop EndIf If $sResponse <> "" Then $iResponseCounter += 1 ConsoleWrite("-------------------- Received Response " & $iResponseCounter & ":" & " --------------------" & @CRLF) ConsoleWrite($sResponse & @CRLF) ; when new Responds, then add If _AddToArray($aResponse, $sResponse, 1) > 0 Then ConsoleWrite("-> added" & @CRLF & @CRLF) Else ConsoleWrite("-> already available" & @CRLF & @CRLF) EndIf ; IP extract und collect $sIP = _ExtractIP($sResponse) If $sIP <> "" Then _AddToArray($aIP, $sIP, 1) EndIf ; spent time determine $iSearchTimer = TimerDiff($hSearchTime) ; when buy the elapsed time, then out If $iSearchTimer >= $iSearchTime Then ExitLoop Else ; Remaining seconds calculate and output as TrayTip $iTimeLeft = Ceiling(($iSearchTime - $iSearchTimer) / 1000) If $iTimeLeft <> $iLastTimeCheck Then TrayTip("SSDP-Discover", "Search for devices via UPnP (" & $iTimeLeft & " seconds)... ", 5, 1) $iLastTimeCheck = $iTimeLeft EndIf EndIf WEnd ; TrayTip close TrayTip("", "", 0) ; Socket close UDPCloseSocket($aSocket) UDPCloseSocket($aSocket) ; UDP end UDPShutdown() ; sort out If IsArray($aIP) Then _ArraySort($aIP, 0, 1) If IsArray($aResponse) Then _ArraySort($aResponse, 0, 1) ; When error exists, then return error If $iFuncError> 0 Then ; return error Return SetError($iError, 0, $iRValue) Else ; normal return Return $iRValue EndIf EndFunc ;==>SSDPdiscover_V2 ; Function extracted from the IP address ReceivedPacket #endregion function definitions #ce
I'm using this script to listen for a broadcast.
Global $g_sIPAdress = "239.255.255.255" Global $g_iPort = 1900 Global $g_iMaxChar = 1024 Global $g_iRecvInterval = 100 Global $g_aSocket Global Enum $iStartupError, $iBindError, $iIPAddrError, $iPortError, $iSocketError, $iShutdownError _Main() Func _Main() _ServerInitialize() Local $sResponse = "" While 1 $sResponse = _ServerReceive() If Not @error And $sResponse <> "" Then ConsoleWrite($sResponse & @CRLF & @CRLF) EndIf Sleep($g_iRecvInterval) WEnd EndFunc Func _ServerInitialize() UDPStartup() If @error Then Return SetError($iStartupError) Else OnAutoItExitRegister("_ServerShutdown") EndIf $g_aSocket = UDPBind($g_sIPAdress, $g_iPort) Switch @error Case 1 Return SetError($iBindError, $iIPAddrError) Case 2 Return SetError($iBindError, $iPortError) EndSwitch EndFunc Func _ServerReceive() Local $sResponse = UDPRecv($g_aSocket, $g_iMaxChar) If @error Then Return SetError($iSocketError, -1, $sResponse) Else Return $sResponse EndIf EndFunc Func _ServerShutdown() UDPCloseSocket($g_aSocket) If @error Then Return SetError($iSocketError) EndIf UDPShutdown() If @error Then Return SetError($iShutdownError) EndIf EndFunc