关于#UDP#同步非阻塞接收的问题,如何解决?

想用VB6做一个UDP接收程序,可以接收局域网内所有终端向该程序指定端口发送的UDP数据。
目前使用下面的代码,遇到的问题是等待接收的时候,程序就会假死,无法进行任何其他操作。希望程序监听UDP数据的时候,可以正常处理其他请求。
在网上找到了用WINSOCK API实现同步非阻塞方式的网络通讯,但不知道如何改成我需要的。
请大家帮忙。

Attribute VB_Name = "modUDPRead"
Option Explicit
Private Const DEFAULT_QUEUE = 1024
Private Const DEFAULT_WAIT_TIME = 50


Private Const WSA_DescriptionLen = 256
Private Const WSA_DescriptionSize = WSA_DescriptionLen + 1
Private Const WSA_SYS_STATUS_LEN = 128
Private Const WSA_SysStatusSize = WSA_SYS_STATUS_LEN + 1
Private Const AF_INET = 2

Private Const SOCK_DGRAM = 2 'UDP
Private Const IPPROTO_UDP = 17 'UDP
Private Const INADDR_ANY As Long = &H0
Private Const IPPROTO_IP As Long = 0
Private Const IP_ADD_MEMBERSHIP As Long = 5

Private Const INADDR_NONE = &HFFFF
Private Const SOCKET_ERROR = -1

Private Type HostEnt
    hName As Long
    hAliases As Long
    hAddrType As Integer
    hLength As Integer
    hAddrList As Long
End Type

Private Type SockAddr
    Sin_Family As Integer
    Sin_Port As Integer
    Sin_Addr As Long
    Sin_Zero(7) As Byte
End Type

Private Type WSADataType
    wVersion As Integer
    wHighVersion As Integer
    szDescription As String * WSA_DescriptionSize
    szSystemStatus As String * WSA_SysStatusSize
    iMaxSockets As Integer
    iMaxUdpDg As Integer
    lpVendorInfo As Long
End Type

Private Type IP_MREQ
  imr_multiaddr As Long
  imr_interface As Long
End Type






Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 
Private Declare Function timeGetTime Lib "winmm.dll" () As Long 

Private Declare Function CloseSocket Lib "ws2_32.dll" Alias "closesocket" (ByVal hSocket As Long) As Long
Private Declare Function Connect Lib "ws2_32.dll" Alias "connect" (ByVal hSocket As Long, Addr As SockAddr, ByVal NameLen As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetHostByName Lib "ws2_32.dll" Alias "gethostbyname" (ByVal HostName As String) As Long
Private Declare Function Htons Lib "ws2_32.dll" Alias "htons" (ByVal HostShort As Integer) As Integer
Private Declare Function iNet_Addr Lib "wsock32.dll" Alias "inet_addr" (ByVal s As String) As Long
Private Declare Function Recv Lib "ws2_32.dll" Alias "recv" (ByVal hSocket As Long, Buf As Any, ByVal BufLen As Long, ByVal Flags As Long) As Long
Private Declare Function Send Lib "ws2_32.dll" Alias "send" (ByVal hSocket As Long, Buf As Any, ByVal BufLen As Long, ByVal Flags As Long) As Long
Private Declare Function Socket Lib "ws2_32.dll" Alias "socket" (ByVal af As Long, ByVal sType As Long, ByVal Protocol As Long) As Long
Private Declare Function WSACleanup Lib "ws2_32.dll" () As Long
Private Declare Function WSAStartup Lib "ws2_32.dll" (ByVal wVR As Long, lpWSAD As WSADataType) As Long


Private Declare Function bind Lib "wsock32.dll" (ByVal s As Long, Addr As SockAddr, ByVal NameLen As Long) As Long
Private Declare Function setsockopt Lib "wsock32.dll" (ByVal s As Long, ByVal level As Long, ByVal optname As Long, ByRef optval As Any, ByVal optlen As Long) As Long


Public Sub UDPClose(ByRef Handle As Long)
    CloseSocket Handle
    WSACleanup
    Handle = -1
End Sub

Public Function UDPOpen(ByVal Host As String, Optional ByVal Port As Long = 502) As Long
    Dim WSAData As WSADataType, SA As SockAddr, Result As Long, iResult As Long
    If WSAStartup(&H202, WSAData) <> 0 Then
        WSACleanup
    Else
        If (InStr(Host, ":") > 0) Then
            If IsNumeric(Right(Host, Len(Host) - InStr(Host, ":"))) = True Then
                Port = CLng(Right(Host, Len(Host) - InStr(Host, ":")))
            End If
            Host = Left(Host, InStr(Host, ":") - 1)
        End If
        Result = Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
        

        Dim mreq As IP_MREQ
        mreq.imr_multiaddr = iNet_Addr("224.0.0.1")
        mreq.imr_interface = iNet_Addr(Host)
        iResult = setsockopt(Result, IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq, Len(mreq))
        If iResult = -1 Then
            CloseSocket Result
            WSACleanup
            Result = -1
        End If
            
        
        SA.Sin_Family = AF_INET
        SA.Sin_Port = Htons(CInt("&H" & Hex(Port)))
        SA.Sin_Addr = INADDR_ANY
        iResult = bind(Result, SA, Len(SA))
        If iResult = -1 Then
            CloseSocket Result
            WSACleanup
            Result = -2
        End If
        
        
    End If
    UDPOpen = Result
End Function

Public Function UDPReadByte(ByVal Handle As Long, Optional ByVal WaitTime As Long = DEFAULT_WAIT_TIME) As Byte()
    Dim T As Double, Result() As Byte, I As Integer
    If Handle = -1 Then Exit Function
    ReDim Result(DEFAULT_QUEUE - 1)
    If WaitTime > 0 Then
        DoEvents
        Sleep2 WaitTime
    End If
    I = Recv(Handle, Result(0), UBound(Result) + 1, 0)
    If I > 0 Then
        ReDim Preserve Result(I - 1)
        UDPReadByte = Result
    End If
End Function


Public Function UDPReadString(ByVal Handle As Long, Optional ByVal WaitTime As Long = DEFAULT_WAIT_TIME) As String
    Dim Data() As Byte
    Data = UDPReadByte(Handle, WaitTime)
    UDPReadString = StrConv(Data, vbUnicode)
End Function


Public Function UDPReadHex(ByVal Handle As Long, Optional ByVal WaitTime As Long = DEFAULT_WAIT_TIME) As String
    Dim Data() As Byte, Result As String, I As Long
    Data = UDPReadByte(Handle, WaitTime)
    For I = 0 To UBound(Data)
        Result = Result & IIf(Data(I) < 16, "0", "") & UCase(Hex(Data(I)))
    Next
    UDPReadHex = Result
End Function


Public Function Sleep2(T As Long)
    Dim Savetime As Long
    Savetime = timeGetTime 
    While timeGetTime < Savetime + T 
      Call Sleep(1) 
        DoEvents 
    Wend
End Function



多线程呀
或者改用异步

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:UDP详解

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^