Websocket 服务器 VB.NET - 数据帧 [英] Websocket Server VB.NET - Data Frame

查看:26
本文介绍了Websocket 服务器 VB.NET - 数据帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 VB.NET 创建最简单的 WebSocket 服务器.我设法实现了握手,但在握手后无法发送消息.以下是我的代码:

I am trying to create the simplest WebSocket server with VB.NET. I manage to implement handshake but fail to send message after handshake. The following is my code:

Dim serverTcp As TcpListener
Dim serverThread As Thread

Sub Main()
    '' Start server
    serverThread = New Thread(AddressOf serverProc)
    serverThread.Start()
End Sub

Private Sub serverProc()
    '' Listen to port 8181
    serverTcp = New TcpListener(8181)
    serverTcp.Start()

    Console.WriteLine("Listen to port 8181 ...")

    '' Accept any connection
    While (True)
        Dim curSocket As Socket = serverTcp.AcceptSocket()
        Dim thread As New Thread(AddressOf clientProc)
        thread.Start(curSocket)
    End While
End Sub

Private Sub clientProc(ByVal sck As Socket)
    Dim netStream As New NetworkStream(sck)
    Dim netReader As New IO.StreamReader(netStream)
    Dim netWriter As New IO.StreamWriter(netStream)

    Dim key As String = ""

    Console.WriteLine("Accept new connection ...")

    '' Reading handshake message
    While (True)
        Dim line As String = netReader.ReadLine()
        If line.Length = 0 Then
            Exit While
        End If

        If (line.StartsWith("Sec-WebSocket-Key: ")) Then
            key = line.Split(":")(1).Trim()
        End If

        Console.WriteLine("Data: " & line)
    End While

    '' Calculate accept-key
    key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
    key = getSHA1Hash(key)

    '' Response handshake message
    Dim response As String
    response = "HTTP/1.1 101 Switching Protocols" & vbCrLf
    response &= "Upgrade: websocket" & vbCrLf
    response &= "Connection: Upgrade" & vbCrLf
    response &= "Sec-WebSocket-Accept: " & key & vbCrLf & vbCrLf
    netWriter.Write(response)
    netWriter.Flush()

    '' Sending Hello World message
    Dim message As String = "Hello World"
    Dim messageByte() As Byte = System.Text.Encoding.UTF8.GetBytes(message)
    Dim startByte() As Byte = {&H0}
    Dim endByte() As Byte = {&HFF}

    sck.Send(startByte, 1, 0)
    sck.Send(messageByte)
    sck.Send(endByte, 1, 0)
End Sub

Function getSHA1Hash(ByVal strToHash As String) As String
    Dim sha1Obj As New Security.Cryptography.SHA1CryptoServiceProvider
    Dim bytesToHash() As Byte = System.Text.Encoding.ASCII.GetBytes(strToHash)
    Dim result As String

    bytesToHash = sha1Obj.ComputeHash(bytesToHash)
    result = Convert.ToBase64String(bytesToHash)

    Return result
End Function

标准说我需要发送0x00字节,接着是UTF8字节,以0xFF字节结束.我已经按照它说的做了,但我的 HTML 客户端无法接收消息.

The standard says that I need to send 0x00 byte, following by byte of UTF8, and end with 0xFF byte. I have done as it say yet my HTML client cannot receive the message.

以下是我的 HTML5 代码:

The following is my HTML5 code:

<script>
if('WebSocket' in window){
  connect('ws://localhost:8181/service');
}

function connect(host) {
  var ws = new WebSocket(host);
  ws.onopen = function () {
    alert('connected');
  };

  ws.onmessage = function (evt) {  
    alert('reveived data:'+evt.data);
  };

  ws.onclose = function () {
    alert('socket closed');
  };
};
</script>

推荐答案

标准说我需要发送0x00字节,后跟UTF8字节,以0xFF字节结束

The standard says that I need to send 0x00 byte, following by byte of UTF8, and end with 0xFF byte

真的?̶你在哪里得到的?̶我不认为有这样的事情在说明书中.

R̶e̶a̶l̶l̶y̶?̶ ̶W̶h̶e̶r̶e̶ ̶d̶i̶d̶ ̶y̶o̶u̶ ̶g̶e̶t̶ ̶t̶h̶a̶t̶?̶ ̶I̶ ̶d̶o̶n̶'̶t̶ ̶t̶h̶i̶n̶k̶ ̶t̶h̶e̶r̶e̶ ̶i̶s̶ ̶s̶o̶m̶e̶t̶h̶i̶n̶g̶ ̶l̶i̶k̶e̶ ̶t̶h̶i̶s̶ ̶i̶n̶ ̶t̶h̶e̶ s̶p̶e̶c̶i̶f̶i̶c̶a̶t̶i̶o̶n̶.

Simonic 在他的评论中声明使用了以 0x00 开头并以 0xFF 结尾在协议的弃用 Hixie-76 变体中.

Simonic statet in his comment that starting with 0x00 and ending with 0xFF was used in the deprecated Hixie-76 variant of the protocol.

查看实际的规范 (RFC 6455).

为了更好地理解,请查看这个很好的答案:

For better understanding, have a look at this great answer:

您发送的帧需要根据WebSocket 帧格式.对于发送消息,此格式为如下:

The frames you're sending need to be formatted according to the WebSocket framing format. For sending messages, this format is as follows:

  • 一个字节,其中包含数据类型(以及一些附加信息这超出了普通服务器的范围)
  • 一个包含长度的字节
  • 两个或八个字节,如果长度不适合第二个字节(第二个字节是一个代码,说明有多少字节用于长度)
  • 实际(原始)数据


我为您翻译了这个 java 实现(以一种快速的方式,可能会有一些错误)到 VB.Net,它正在工作:


I translated this java implementation for you (in a quick'n'dirty way, there may be some errors) to VB.Net, and it's working:

Sub SendMessage(sck As Socket, message as String)
    Dim  rawData =  System.Text.Encoding.UTF8.GetBytes(message)

    Dim frameCount = 0
    Dim frame(10) As byte

    frame(0) = cbyte(129)

    if rawData.length <= 125 Then
        frame(1) = CByte( rawData.length)
        frameCount = 2
    else if rawData.length >= 126 AndAlso rawData.length <= 65535
        frame(1) = CByte( 126)
        Dim len = cbyte(rawData.length)
        frame(2) = CByte(((len >> 8 ) & CByte(255)))
        frame(3) = CByte((len & CByte(255)))
        frameCount = 4
    else
        frame(1) = CByte( 127)
        Dim len = CByte( rawData.length)
        frame(2) = CByte(((len >> 56 ) & CByte(255)))
        frame(3) = CByte(((len >> 48 ) & CByte(255)))
        frame(4) = CByte(((len >> 40 ) & CByte(255)))
        frame(5) = CByte(((len >> 32 ) & CByte(255)))
        frame(6) = CByte(((len >> 24 ) & CByte(255)))
        frame(7) = CByte(((len >> 16 ) & CByte(255)))
        frame(8) = CByte(((len >> 8 ) & CByte(255)))
        frame(9) = CByte((len & CByte(255)))
        frameCount = 10
    End If

    Dim bLength = frameCount + rawData.length
    Console.WriteLine(frameCount)
    Console.WriteLine(rawData.length)
    Dim reply(bLength+1) as byte

    Dim bLim = 0
    for i=0 to frameCount-1
        Console.WriteLine(blim)
        reply(bLim) = frame(i)
        bLim += 1
    Next
    
    for i=0 to rawData.length-1
        Console.WriteLine(blim)
        reply(bLim) = rawData(i)
        bLim += 1
    Next
    
    sck.Send(reply)
End Sub

您可以在 clientProc 中使用它:

You can use it in your clientProc:

'' Sending Hello World message
SendMessage(sck, "Hello World")

这篇关于Websocket 服务器 VB.NET - 数据帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆