找回密码
 加入
搜索
查看: 475|回复: 4

[网络通信] [已解决]有没有内置函数实现UDP单端口通信的例子?

[复制链接]
发表于 2023-5-5 11:35:36 | 显示全部楼层 |阅读模式
本帖最后由 gyp2000 于 2023-5-16 00:09 编辑

内置函数实现UDP单端口通信

服务端和客户端都仅使用一个端口。
客户端使用系统分配的随机端口。
图例:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2023-5-6 01:08:51 | 显示全部楼层
本帖最后由 白嫖之黑 于 2023-5-6 03:27 编辑

一般不都是单端口吗。套接字可以实现通讯
 楼主| 发表于 2023-5-6 19:11:24 | 显示全部楼层
白嫖之黑 发表于 2023-5-6 01:08
一般不都是单端口吗。套接字可以实现通讯

目前AU3里, TCP是单端口。UDP的话,自己造轮子也可以实现单端口。
如果仅使用内置函数,目前还没看到 ,通过内置函数实现UDP单端口通讯的例子。
 楼主| 发表于 2023-5-16 00:07:29 | 显示全部楼层
本帖最后由 gyp2000 于 2023-5-16 00:28 编辑
#include <GUIConstantsEx.au3>
Global $S_Socket, $C_Socket

Example()

Func Example()
        UDPStartup()
        Local $sReceived, $maxlen
        Local $hGUI = GUICreate("UDP通讯示例")
        Local $idEXIT = GUICtrlCreateButton("退出", 310, 370, 85, 25)
        Local $Label1 = GUICtrlCreateLabel("", 10, 10, 160, 25)
        Local $Label2 = GUICtrlCreateLabel("", 10, 42, 160, 25)
        Local $Label3 = GUICtrlCreateLabel("Server 返回消息:", 10, 74, 160, 25)

        GUISetState(@SW_SHOW, $hGUI)
        $S_Socket = _UDPBind("0.0.0.0", 0)
        If @error Then Exit MsgBox(0, "", "服务端:" & @CRLF & "无法绑定, 错误代码: " & @error)
        GUICtrlSetData($Label1, "Server 监听端口:" & @extended)
        $C_Socket = _UDPOpen("127.0.0.1", $S_Socket[3])
        If @error Then Exit MsgBox(0, "", "客户端:" & @CRLF & "无法连接, 错误代码: " & @error)
        GUICtrlSetData($Label2, "Client 监听端口:" & @extended)
        AdlibRegister("_Time", 1000)

        While 1
                Switch GUIGetMsg()
                        Case $GUI_EVENT_CLOSE, $idEXIT
                                ExitLoop
                EndSwitch

                $maxlen = _Datelen($S_Socket)
                If $maxlen Then
                        $sReceived = _UDPRecv($S_Socket, $maxlen, 2)
                        $S_Socket[2] = $sReceived[1]
                        $S_Socket[3] = $sReceived[2]
                        UDPSend($S_Socket, @HOUR & ":" & @MIN & ":" & @SEC)
                EndIf

                $maxlen = _Datelen($C_Socket)
                If $maxlen Then
                        $sReceived = _UDPRecv($C_Socket, $maxlen)
                        GUICtrlSetData($Label3, "Server 返回消息:" & $sReceived)
                EndIf
        WEnd

        UDPCloseSocket($S_Socket)
        UDPCloseSocket($C_Socket)
        UDPShutdown()
        GUIDelete($hGUI)
EndFunc   ;==>Example

Func _Time()
        UDPSend($C_Socket, @SEC)
EndFunc   ;==>_Time

Func _UDPOpen($sIPAddr, $iPort)
        Local $aSocket = _UDPBind("0.0.0.0", 0)
        $aSocket[2] = $sIPAddr
        $aSocket[3] = $iPort
        Return SetError(@error, @extended, $aSocket)
EndFunc   ;==>_UDPOpen

Func _UDPBind($sIPAddr, $iPort)
        Local $aSocket, $loop
        If $iPort = 0 Then
                Do
                        $loop += 1
                        $iPort = Random(49152, 65535, 1)
                        $aSocket = UDPBind($sIPAddr, $iPort)
                        If $loop > 15000 Then ExitLoop
                Until @error <> 10048
        Else
                $aSocket = UDPBind($sIPAddr, $iPort)
        EndIf
        If @error Then Return SetError(@error, 0, $aSocket)
        DllCall("Ws2_32.dll", "long", "setsockopt", "handle", $aSocket[1], "long", 0xffff, "long", 0x20, "long*", 1, "long*", 4) ;允许广播地址
        Return SetError(0, $aSocket[3], $aSocket)
EndFunc   ;==>_UDPBind

Func _UDPRecv(ByRef $aSocket, $maxlen, $flag = 0)
        Local $sRecv = UDPRecv($aSocket, $maxlen, $flag)
        Return SetError(@error, 0, $sRecv)
EndFunc   ;==>_UDPRecv

Func _Datelen(ByRef $aSocket)
        Local $aRet = DllCall("Ws2_32.dll", "int", "ioctlsocket", "uint", $aSocket[1], "long", 0x4004667F, "ulong*", 0) ;查询接收缓冲区数据长度
        If Not @error Then Return SetError(0, 0, $aRet[3])
        Return SetError(@error, 0, 0)
EndFunc   ;==>_Datelen





示例里的端口随机,使用了随机函数实现。这样可以让代码易读一些。
UDPRecv函数在无数据的时候会堵塞100毫秒,所以读取前检查缓冲区长度再读取数据,这样可以避免堵塞的发生。



您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-3-28 19:17 , Processed in 0.072795 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表