当前位置:   article > 正文

通用Websocket客户端组件,适用于C#,VB.net与VB6 的开发使用,支持WSS_vb.net 开发服务端程序 操作wps

vb.net 开发服务端程序 操作wps

近期由于业务需要,需要与视频会议服务器整合开发,由于会议服务器的控制方式要求采用Websocket方式,并且是WSS(加密Websocket协议), 由于一直采用VB6、VB.Net开发,因此就在网上搜索是否有合适的解决方案,花了两天时间都没有找到合适的。虽然笔者找到一些实现方案,但是要么就是VB实现的,不支持WSS,要么就是C#实现的,不支持VB开发,要么不支持64位Windows程序调用,反正没有找到合适的。因此不得不让笔者花时间来自己实现一个。
笔者,完全按照H5的Websocket对象实现了一个Websocket组件,用于支持VB6、VB.Net与C#等程序语言调用、支持原生64位与32位实现、支持OpenSSL实现安全套接字的WSS协议。Websocket代码完全采用C/C++实现,Socket I/O采用异步高性能调用方式。
Websocket组件完全参照H5的Websocket实现方式,具备的方法、属性与事件如下:
组件名称:VBToolsLib.Websocket,采用Com方式实现,同时编译成x86与x64版本
以编译的动态库形式发布,需要执行Regsvr32程序来注册这个COM组件,在64位操作系统下建议两个版本都注册。
该组件完全永久免费使用,没有任何功能限制,也没有时间限制,确保不含任何失效时间或者远程下发关闭的后门,可以长期永久免费无任何限制地使用。由于实现源码逻辑复杂,编译复杂,所以不提供组件的实现源码,省得麻烦。如有部分定制需求,可在评论区发言,笔者酌情修补。
VB,VB.NET, C# 都需要添加引用,引用的组件库名为:VBToolsLib,如下图所示:
在这里插入图片描述
可以在github里下载这个组件:
https://github.com/wenshui2008/WebsocketVB

VBToolsLib.WebSocket 组件属性

属性名称说明
readyState

只读属性 readyState 表示连接状态,以下值:

0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开。
bufferedAmount只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本消息条数。每调用一次send,就会在组件的队列里添加一条消息,如果网速不足够快消息不一定会立即发送出去,需要排队等待。

VBToolsLib.WebSocket 组件方法

方法名称方法说明
open(sUrl)建立连接,输入的sUrl为Websocket的服务地址,例如:ws://192.168.1.200:3000、wss://192.168.1.200:3000
send(msg)使用连接发送数据,msg为要发送的文本字符串
close关闭连接
setwindowhandle64(hwnd)一个窗口句柄,Win32的HWND类型的句柄,C#与VB.Net的form的Handle,VB6的Form的 hWnd,为什么要增加这个方法呢,因为组件采用多线程方式,用单独的线程来处理网络I/O,这个方法就是用来让组件关联主线程、并在主线程上进行事件回调的。这个方法是H5的Websocket对象没有的。
setHttpHeader(name, value)设置http请求头字段,如果输入的请求头字段不存在,则添加一个;如果存在,则替换存在的头。在open方法调用前此方法设置的头可以有效,否则只能在close调用后重新调用open方法才能有效。这个方法是H5的Websocket对象没有的。
例如:setHttpHeader(“My-Header”,“Some Value”)

VBToolsLib.WebSocket 支持的事件

事件名称事件说明
onopen连接成功建立时触发
onmessage(data)客户端接收到服务端消息数据时触发
onerror(errmsg)通信发生错误时触发
onclose连接关闭时触发

以下是各种语言调用的样本代码,非常简单,现在一一介绍。

VB.Net方式

1)在Form的Load事件创建组件,并设置主窗口句柄,调用setwindowhandle64来设置窗口句柄,setwindowhandle为32位版本
2)在Form的Close事件里,注销与窗口句柄的关联,这步不是必须
3)实现接收组件的事件回调方法,websock_onopen、websock_onmessage、websock_onclose与websock_onerror等事件,
4)调用send发送消息,调用close关闭连接

Public Class mainForm
    Dim WithEvents websock As VBToolsLib.Websocket

    Delegate Sub appendText(s As String)
    Dim useSetwindowhandle As Boolean = False


    Private Sub mainForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim count As Integer

        'TextBox.CheckForIllegalCrossThreadCalls = False
        '在窗口的初始化事件里创建Websocket对象
        websock = New VBToolsLib.Websocket

        '接着关联一个主线程窗口句柄便于接收Websocket消息
        'setwindowhandle方法用于设置关联窗口句柄(仅用于32位版本),setwindowhandle64为64位版本
        '仅需要调用这两个方法中的一个即可,64位版本必须用setwindowhandle64方法
        'websock.setwindowhandle(Me.Handle)
        'setwindowhandle64 即能够用于Windows 32位又能用于64位
        websock.setwindowhandle64(Me.Handle)
        '因为调用了setwindowhandle64方法,所以设置标志为True
        useSetwindowhandle = True
        '任何时间都可以调用bufferedAmount属性获取尚未发送的缓冲数目,这里仅是演示
        count = websock.bufferedAmount
		'在调用open 方法之前可以设置Http 请求头,这些头放在标准的HTTP协议请求头里发送给服务器
        websock.setHttpHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36")
        websock.setHttpHeader("Cookie", "XMPlayer=V1.0; PHPSESSID=3nm364h6bu2i80lp4esik5ki56")

        urlInput.Text = "wss://192.168.2.134:3000/"

        If (IntPtr.Size = 8) Then
            Me.Text &= " (x64)"
        End If
    End Sub

    Private Sub mainForm_FormClosed(sender As System.Object, e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
        '在窗口关闭事件里取消窗口句柄关联,不是必须
        If useSetwindowhandle Then
            websock.setwindowhandle(0)
        End If
    End Sub

    Private Sub OpenBtn_Click(sender As System.Object, e As System.EventArgs) Handles OpenBtn.Click
        Dim url
        url = urlInput.Text

        If url <> "" Then
            '连接服务器,执行的是异步操作,只能通过监听onopen与onerror事件来判断是否成功
            websock.open(url)
        End If
    End Sub

    Private Sub CloseBtn_Click(sender As System.Object, e As System.EventArgs) Handles CloseBtn.Click
        websock.close()
    End Sub

    Private Sub SendBtn_Click(sender As System.Object, e As System.EventArgs) Handles SendBtn.Click
        Dim sMsg As String = msgInputBox.Text

        If sMsg <> "" Then
            websock.send(sMsg)
        End If
    End Sub

    Private Sub websock_onopen() Handles websock.onopen
        Dim sTime As String = DateDiff("s", "1970-01-01 00:00:00", Now)
        Dim sMsg = ""
        websock.send("login: " & sTime)

        sMsg = "OnOpen" & Chr(13) & Chr(10)
        If useSetwindowhandle Then
            msgListbox.AppendText(sMsg)
        Else
            '如果没有调用setwindowhandle关联窗体句柄,就必须用委托方式,否则可能会有多线程界面死锁问题
            Me.Invoke(New appendText(AddressOf AppendTextMethod), sMsg)
        End If
    End Sub

    Private Sub websock_onmessage(ByVal msg As String) Handles websock.onmessage
        Dim sMsg As String

        sMsg = msg & Chr(13) & Chr(10)
        If useSetwindowhandle Then
            msgListbox.AppendText(sMsg)
        Else
            '如果没有调用setwindowhandle(x64),就必须用委托方式,否则会有多线程界面死锁问题
            Me.Invoke(New appendText(AddressOf AppendTextMethod), sMsg)
        End If

        '这里演示处理消息,具体业务逻辑的实现可能不是这样的,这里仅为演示
        If (msg = "[MSG]:close") Then
            websock.close()
        ElseIf (msg.Substring(0, 14) = "[MSG]:foreward") Then
            Dim newmsg = msg.Substring(14)
            '演示将消息重新转发出去,具体业务逻辑由调用者自己实现,这里仅仅为演示
            websock.send("[MSG]:This is a foreward MSG:" & newmsg)
        End If
    End Sub

    Private Sub websock_onclose() Handles websock.onclose
        Dim sMsg As String
        sMsg = "Onclose" & Chr(13) & Chr(10)
        If useSetwindowhandle Then
            msgListbox.AppendText(sMsg)
        Else
            '没有调用setwindowhandle(x64),就必须用委托方式,否则有多线程问题
            Me.Invoke(New appendText(AddressOf AppendTextMethod), sMsg)
        End If
    End Sub

    Private Sub websock_onerror(ByVal msg As String) Handles websock.onerror
        Dim sMsg As String

        sMsg = "onerror:" & msg & Chr(13) & Chr(10)
        If useSetwindowhandle Then
            msgListbox.AppendText(sMsg)
        Else
            '调用了 setwindowhandle(x64) 就不用委托方式了,否则会有多线程问题
            Me.Invoke(New appendText(AddressOf AppendTextMethod), sMsg)
        End If
    End Sub

    Public Sub AppendTextMethod(msgText As String)
        msgListbox.AppendText(msgText)
    End Sub
End Class


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

用VB.NET实现的界面如下:
在这里插入图片描述

C#的实现代码

过程与VB.NET的过程完全一样。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CSTester
{
    public partial class mainForm : Form
    {
        VBToolsLib.Websocket websock;

        public mainForm()
        {
            InitializeComponent();
        }

        private void mainForm_Load(object sender, EventArgs e)
        {
            int count;
            
            //在窗口的初始化事件里创建Websocket对象
            websock = new VBToolsLib.Websocket();

            //关联主线程句柄便于接收Websocket消息
            //setwindowhandle方法用于关联窗口句柄,setwindowhandle64为64位版本,调用其中一个即可
            //websock.setwindowhandle((int)this.Handle);
            websock.setwindowhandle64((long)this.Handle);
            
			// 在调用open 方法之前可以设置Http 请求头,这些头放在标准的HTTP协议请求头里发送给服务器
            websock.setHttpHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36");
            websock.setHttpHeader("Cookie", "XMPlayer=V1.0; PHPSESSID=3nm364h6bu2i80lp4esik5ki56");

            urlInput.Text = "wss://192.168.2.134:3000/";
            //演示获取属性
            count = websock.bufferedAmount;
            //C#方式的设置事件
            websock.onopen    += websocket_onopen;
            websock.onclose   += websocket_onclose;
            websock.onmessage += websocket_onmessage;
            websock.onerror   += websocket_onerror;

            if (IntPtr.Size == 8) {
                this.Text += " (x64)";
            }
        }

        private void mainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //在窗口关闭事件里取消窗口句柄关联,不是必须
            websock.setwindowhandle(0);
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            string sUrl = urlInput.Text;

            if (sUrl != "") {
                websock.open(sUrl);
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            websock.close();
        }
        
        private void btnSend_Click(object sender, EventArgs e)
        {
            string sMsg = msgInput.Text;

            if (sMsg != "")
            {
                websock.send(sMsg);
            }
        }

        private void websocket_onopen()
        {
            string sTime;
            string sMsg;

            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);

            sTime = Convert.ToInt64(ts.TotalSeconds).ToString();
            //这里演示给服务器发送一个消息,具体业务逻辑应该在服务器上实现
            websock.send("login: " + sTime);

            sMsg = "OnOpen\r\n";
            msgListbox.AppendText(sMsg);
        }

        private void websocket_onclose()
        {
            string sMsg;

            sMsg = "Onclose\r\n";

            msgListbox.AppendText(sMsg);
        }

        private void websocket_onmessage(string msg)
        {
            string sMsg;

            sMsg = msg + "\r\n";

            msgListbox.AppendText(sMsg);
            //这里演示处理消息,具体业务逻辑的实现可能不是这样的,这里仅为演示
            if (msg == "[MSG]:close")
            {
                websock.close();
            }
            else if (msg.Substring(0, 14) == "[MSG]:foreward")
            {
                string newmsg = msg.Substring(14);
                //演示将消息重新转发出去,具体业务逻辑由调用者自己实现,这里仅仅为演示
                websock.send("[MSG]:This is a foreward MSG:" + newmsg);
            }
        }

        private void websocket_onerror(string errmsg)
        {
            string sMsg;

            sMsg = "onerror:" + errmsg + "\r\n";

            msgListbox.AppendText(sMsg);
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

C#的界面如下:
在这里插入图片描述

VB6 调用的实现:

调用过程与以上一样,仅仅是VB6的代码不一样
VB6代码如下:

Dim WithEvents websock As VBToolsLib.Websocket
Private Sub Form_Load()
    Dim count As Integer
    
    Set websock = New VBToolsLib.Websocket
    '设置一个窗口关联句柄,VB6仅支持32位版本即可
    websock.setwindowhandle (Me.hWnd)
        
    count = websock.bufferedAmount
    '在调用open 方法之前可以设置Http 请求头,这些头放在标准的HTTP协议请求头里发送给服务器
    websock.setHttpHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; VB6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
    websock.setHttpHeader "Cookie", "XMPlayer=V1.0; PHPSESSID=3nm364h6bu2i80lp4esik5ki56"

    urlInput.Text = "wss://192.168.2.134:3000/"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    websock.setwindowhandle (0)
End Sub

Private Sub btnOpen_Click()
    Dim url As String

    url = urlInput.Text

    If url <> "" Then
        websock.open (url)
    End If
End Sub

Private Sub btnClose_Click()
    websock.Close
End Sub

Private Sub btnSend_Click()
    Dim sMsg As String
    sMsg = msgInput.Text

    If sMsg <> "" Then
        websock.send (sMsg)
    End If
End Sub

Private Sub websock_onopen()
    Dim sTime As String
    Dim sMsg As String
    
    sTime = DateDiff("s", "1970-01-01 00:00:00", Now)
    '演示发送消息,具体业务逻辑由开发者自己实现,这里仅为演示代码
    websock.send ("login: " & sTime)

    sMsg = "OnOpen" & Chr(13) & Chr(10)
    msgListbox.Text = msgListbox.Text & sMsg

End Sub

Private Sub websock_onclose()
    Dim sMsg As String
    
    sMsg = "Onclose" & Chr(13) & Chr(10)
    msgListbox.Text = msgListbox.Text & sMsg
    
End Sub
Private Sub websock_onmessage(ByVal msg As String)
    
    Dim sMsg As String

    sMsg = msg & Chr(13) & Chr(10)
    msgListbox.Text = msgListbox.Text & sMsg
    '仅为演示处理消息,具体业务逻辑应该由开发者自己实现
    If (msg = "[MSG]:close") Then
       websock.Close
    ElseIf Mid(msg, 1, 14) = "[MSG]:foreward" Then
       Dim newmsg
       
       newmsg = Mid(msg, 15)

       websock.send ("[MSG]:This is a foreward MSG:" & newmsg)
    End If
End Sub

Private Sub websock_onerror(ByVal errmsg As String)
    Dim sMsg As String
    
    sMsg = "onerror:" & errmsg & Chr(13) & Chr(10)
    
    msgListbox.Text = msgListbox.Text & sMsg
End Sub

Public Sub AppendTextMethod(msgText As String)
    'msgListbox.AppendText (msgText)
End Sub
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

VB6的界面如下:

在这里插入图片描述
注意:由于VB6本身不支持64位代码,因此只能用32位的组件。

该组件用于VB/C#的Websocket服务器端代码暂时没有时间实现,后续再实现。

测试程序的全部源代码在这:
https://github.com/wenshui2008/WebsocketVB

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/164624
推荐阅读
相关标签
  

闽ICP备14008679号