Websocket Server VB.NET - 数据框架

时间:2012-10-17 09:32:53

标签: vb.net html5 websocket

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

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客户端无法接收消息。

以下是我的HTML5代码:

<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>

1 个答案:

答案 0 :(得分:2)

  

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

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

Simonic状态在他的评论中以0x00开头并以0xFF结尾用于协议的弃用的Hixie-76变体。

查看实际的specification (RFC 6455)


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

  

您要发送的帧需要按照格式进行格式化   WebSocket框架格式。对于发送消息,此格式为   如下:

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

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

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

中使用它
'' Sending Hello World message
SendMessage(sck, "Hello World")

enter image description here