首页 云计算

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁

分类:云计算
字数: (3865)
阅读: (4285)
内容摘要:VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁,

在一些老旧的工业控制系统或者特定的金融软件中,我们仍然能看到 DDE (Dynamic Data Exchange) 的身影。虽然现在更流行的是 TCP/IP 和消息队列,但 DDE 凭借其简单性,仍然在某些特定场景下发挥着作用。本文将深入探讨如何使用 VB.NET 构建一个 DDE 服务器,并分享一些实战中的避坑经验。

DDE 底层原理剖析

DDE 是一种在 Windows 应用程序之间传输数据的机制。它依赖于 Windows 消息传递系统,通过共享内存进行数据交换。DDE 通信涉及三个角色:服务器 (Server)、客户端 (Client) 和会话 (Conversation)。服务器提供数据,客户端请求数据,而会话则定义了服务器和客户端之间的连接。DDE 使用预定义的 Windows 消息(如 WM_DDE_INITIATEWM_DDE_REQUESTWM_DDE_DATA)进行通信。

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁

在实际应用中,DDE 服务器通常会监听特定的服务名 (Service Name) 和主题名 (Topic Name)。客户端通过指定服务名和主题名来找到服务器,并建立连接。一旦连接建立,客户端就可以请求服务器提供特定项 (Item) 的数据。服务器收到请求后,会将数据通过 WM_DDE_DATA 消息发送给客户端。

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁

VB.NET 实现 DDE 服务器的具体代码

下面是一个简单的 VB.NET DDE 服务器示例,用于接收和响应客户端的 DDE 请求。

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁
Imports System.Runtime.InteropServices

Public Class DDEServer

    Private Const WM_DDE_INITIATE As Integer = &H3E0
    Private Const WM_DDE_TERMINATE As Integer = &H3E1
    Private Const WM_DDE_ADVISE As Integer = &H3E2
    Private Const WM_DDE_UNADVISE As Integer = &H3E3
    Private Const WM_DDE_ACK As Integer = &H3E4
    Private Const WM_DDE_DATA As Integer = &H3E5
    Private Const WM_DDE_REQUEST As Integer = &H3E6
    Private Const WM_DDE_POKE As Integer = &H3E7
    Private Const WM_DDE_EXECUTE As Integer = &H3E8

    Private serviceName As String = "MyDDE"
    Private topicName As String = "System"

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function PostMessage(hWnd As IntPtr, Msg As Integer, wParam As IntPtr, lParam As IntPtr) As Boolean
    End Function

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
    End Function

    <DllImport("user32.dll")>
    Private Shared Function GlobalAddAtom(lpString As String) As Short
    End Function

    <DllImport("user32.dll")>
    Private Shared Function GlobalDeleteAtom(nAtom As Short) As Short
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function GetClassName(hWnd As IntPtr, lpClassName As StringBuilder, nMaxCount As Integer) As Integer
    End Function


    Public Sub New()
        ' 注册服务名和主题名
        Dim serviceAtom As Short = GlobalAddAtom(serviceName)
        Dim topicAtom As Short = GlobalAddAtom(topicName)
    End Sub

    Public Function WndProc(ByVal m As Message) As Boolean
        Select Case m.Msg
            Case WM_DDE_INITIATE
                ' 客户端尝试连接
                Dim serviceAtomClient As Short = CLng(m.WParam.ToInt32())
                Dim topicAtomClient As Short = CLng(m.LParam.ToInt32())

                ' 验证服务名和主题名
                If GlobalGetAtomName(serviceAtomClient) = serviceName AndAlso GlobalGetAtomName(topicAtomClient) = topicName Then
                    ' 发送 ACK 消息
                    Dim lParam As IntPtr = MakeLong(GlobalAddAtom(serviceName), GlobalAddAtom(topicName))
                    PostMessage(m.WParam, WM_DDE_ACK, m.HWnd, lParam)
                    Return True
                End If

            Case WM_DDE_REQUEST
                ' 客户端请求数据
                Dim itemAtom As Short = CLng(m.LParam.ToInt32())
                Dim itemName As String = GlobalGetAtomName(itemAtom)

                If itemName = "time" Then
                    ' 返回当前时间
                    Dim data As String = DateTime.Now.ToString()
                    Dim dataAtom As Short = GlobalAddAtom(data)
                    Dim lParamData As IntPtr = MakeLong(0, dataAtom)
                    PostMessage(m.WParam, WM_DDE_DATA, m.HWnd, lParamData)
                    Return True
                End If
        End Select

        Return False
    End Function

    Private Function GlobalGetAtomName(ByVal atom As Short) As String
        Dim buffer As New StringBuilder(256)
        GlobalGetAtomNameAPI(atom, buffer, 256)
        Return buffer.ToString()
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Private Shared Function GlobalGetAtomNameAPI(ByVal nAtom As Short, ByVal lpBuffer As StringBuilder, ByVal nSize As Integer) As Short
    End Function

    Private Function MakeLong(low As Integer, high As Integer) As IntPtr
        Return New IntPtr((high << 16) Or (low And &HFFFF))
    End Function

End Class

代码解释:

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁
  • 首先,我们导入必要的 Windows API 函数,例如 SendMessagePostMessageFindWindow 等。这些函数用于发送和接收 Windows 消息,以及查找窗口。
  • WM_DDE_INITIATE 消息用于客户端发起连接请求,服务器需要验证服务名和主题名,如果匹配,则发送 WM_DDE_ACK 消息确认连接。
  • WM_DDE_REQUEST 消息用于客户端请求数据,服务器需要根据请求的项 (Item) 返回相应的数据,并通过 WM_DDE_DATA 消息发送给客户端。
  • GlobalAddAtomGlobalDeleteAtom 函数用于注册和删除全局原子,原子是 Windows 中用于标识字符串的唯一标识符。

实战避坑经验总结

  • 字符集问题: DDE 依赖于 ANSI 字符集,因此在处理字符串时需要注意字符集转换,避免乱码问题。
  • 内存管理: DDE 使用共享内存进行数据交换,需要小心管理内存,避免内存泄漏。
  • 消息循环: DDE 服务器需要运行在一个消息循环中,才能接收和处理 DDE 消息。可以使用 Application.Run 或者手动创建消息循环。
  • 权限问题: 在某些情况下,DDE 通信可能受到权限限制,需要确保服务器和客户端都具有足够的权限。
  • 并发处理: 如果 DDE 服务器需要处理多个客户端的请求,需要考虑并发处理的问题,可以使用多线程或者异步编程来提高性能。此外,需要注意线程安全问题,避免数据竞争。

总结

尽管 DDE 已经是一种相对古老的技术,但在某些特定场景下仍然具有一定的价值。通过 VB.NET 编写 DDE 服务器,可以实现应用程序之间的数据交换,从而构建更复杂的系统。希望本文能够帮助你理解 DDE 的原理,并掌握使用 VB.NET 构建 DDE 服务器的方法。

在实际项目中,我们也可以考虑使用其他更现代的技术,例如 TCP/IP、消息队列(如 RabbitMQ、Kafka)或者 RESTful API。这些技术具有更高的性能、更好的可扩展性和更强的安全性,能够满足更复杂的需求。例如,使用 Nginx 作为反向代理服务器,可以实现负载均衡,提高系统的并发连接数,并通过宝塔面板简化服务器管理。但对于一些特定的遗留系统,DDE 仍然是一个可行的解决方案。

VB.NET 实现 DDE 服务端:构建高效的数据交换桥梁

转载请注明出处: 代码一只喵

本文的链接地址: http://m.acea2.store/blog/100170.SHTML

本文最后 发布于2026-04-10 00:33:43,已经过了17天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 螺蛳粉真香 4 天前
    VB.NET 写的代码,感觉年代感满满啊,不过很实用!
  • 煎饼果子 4 天前
    VB.NET 写的代码,感觉年代感满满啊,不过很实用!
  • 西瓜冰冰凉 3 天前
    VB.NET 写的代码,感觉年代感满满啊,不过很实用!