Websocket Server VB.NET - 数据框架 [英] Websocket Server VB.NET - Data Frame
问题描述
我正在尝试使用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
byte,后跟UTF8的字节,a nd以 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̶̶̶̶̶̶̶̶̶̶ ̶我不认为有这样的事情在说明书中。
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:
- 包含数据类型的一个字节(以及一些其他信息
超出了普通服务器的范围) - 包含长度的一个字节
- 如果长度为2或8个字节不适合
的第二个字节(第二个字节是一个代码,说明用于长度的
有多少字节) - 实际(原始)数据
- one byte which contains the type of data (and some additional info which is out of scope for a trivial server)
- one byte which contains the length
- either two or eight bytes if the length does not fit in the second byte (the second byte is then a code saying how many bytes are used for the length)
- the actual (raw) data
我翻译了这个 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
您可以在<$中使用它c $ c> clientProc :
'' Sending Hello World message
SendMessage(sck, "Hello World")
这篇关于Websocket Server VB.NET - 数据框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!