问题描述
我不明白为什么我不能使下面的代码工作。我想用JavaScript连接到我的服务器控制台应用程序。然后将数据发送到服务器。
I don't understand why I cannot make the following code work. I want to connect with JavaScript to my server console application. And then send data to the server.
这是服务器代码:
static void Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 9998);
server.Start();
var client = server.AcceptTcpClient();
var stream = client.GetStream();
while (true)
{
var buffer = new byte[1024];
// wait for data to be received
var bytesRead = stream.Read(buffer, 0, buffer.Length);
var r = System.Text.Encoding.UTF8.GetString(buffer);
// write received data to the console
Console.WriteLine(r.Substring(0, bytesRead));
}
}
这里是JavaScript:
and here is the JavaScript:
var ws = new WebSocket("ws://localhost:9998/service");
ws.onopen = function () {
ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("Message is received...");
};
ws.onclose = function () {
// websocket is closed.
alert("Connection is closed...");
};
当我运行该代码时,会发生以下情况:
When I run that code this is what happens:
请注意,当我运行JavaScript时,服务器接受并成功建立连接。 JavaScript无法发送数据。每当我放置send方法时,即使建立了连接也不会发送。如何使这项工作?
Note that when I run the JavaScript the server accepts and successfully establishes a connection. JavaScript is not able to send data though. Whenever I place the send method it will not send even though a connection is established. How can I make this work?
推荐答案
WebSockets是依赖于TCP流连接的协议。虽然WebSockets是基于消息的协议。
WebSockets is protocol that relies on TCP streamed connection. Although WebSockets is Message based protocol.
如果你想实现自己的协议,那么我建议使用最新和稳定的规范(适用于18/04/12)。
该规范包含有关握手和成帧的所有必要信息。以及关于从浏览器端以及从服务器端行为的场景的大部分描述。
强烈建议在实现代码时遵循有关服务器端的建议。
If you want to implement your own protocol then I recommend to use latest and stable specification (for 18/04/12) RFC 6455.This specification contains all necessary information regarding handshake and framing. As well most of description on scenarios of behaving from browser side as well as from server side.It is highly recommended to follow what recommendations tells regarding server side during implementing of your code.
简而言之,我将描述使用WebSockets,如下所示:
In few words, I would describe working with WebSockets like this:
-
创建服务器套接字(System.Net.Sockets)将其绑定到特定端口,并保持通过异步接受连接来监听。类似的东西:
Create server Socket (System.Net.Sockets) bind it to specific port, and keep listening with asynchronous accepting of connections. Something like that:
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
serverSocket.Listen(128);
serverSocket.BeginAccept(null, 0, OnAccept, null);
你应该有接受功能OnAccept将实现握手。如果系统每秒处理大量连接,它必须在另一个线程中。
You should have accepting function "OnAccept" that will implement handshake. In future it has to be in another thread if system is meant to handle huge amount of connections per second.
private void OnAccept(IAsyncResult result) {
try {
Socket client = null;
if (serverSocket != null && serverSocket.IsBound) {
client = serverSocket.EndAccept(result);
}
if (client != null) {
/* Handshaking and managing ClientSocket */
}
} catch(SocketException exception) {
} finally {
if (serverSocket != null && serverSocket.IsBound) {
serverSocket.BeginAccept(null, 0, OnAccept, null);
}
}
}
建立连接后,你必须做握手。根据规范,建立连接后,您将收到基本的HTTP请求一些信息。示例:
After connection established, you have to do handshake. Based on specification 1.3 Opening Handshake, after connection established you will receive basic HTTP request with some information. Example:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
此示例基于协议13的版本。请记住,旧版本有一些差异,但大多数最新版本是交叉兼容的。不同的浏览器可能会向您发送一些其他数例如浏览器和操作系统的详细信息,缓存和其他。
This example is based on version of protocol 13. Bear in mind that older versions have some differences but mostly latest versions are cross-compatible. Different browsers may send you some additional data. For example Browser and OS details, cache and others.
根据提供的握手详细信息,您必须生成答案行,它们大多相同,但包含Accpet-Key ,这是基于提供的Sec-WebSocket-Key。在规范1.3中,清楚地描述了如何生成响应密钥。
这是我在V13上使用的函数:
Based on provided handshake details, you have to generate answer lines, they are mostly same, but will contain Accpet-Key, that is based on provided Sec-WebSocket-Key. In specification 1.3 it is described clearly how to generate response key.Here is my function I've been using for V13:
static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private string AcceptKey(ref string key) {
string longKey = key + guid;
SHA1 sha1 = SHA1CryptoServiceProvider.Create();
byte[] hashBytes = sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(longKey));
return Convert.ToBase64String(hashBytes);
}
握手答案如下:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
但是,接受密钥必须是基于客户端提供的密钥和我之前提供的方法AcceptKey生成的密钥。同样,请确保在接受键的最后一个字符后面添加两行\\\\\\\ n。
But accept key have to be the generated one based on provided key from client and method AcceptKey I provided before. As well, make sure after last character of accept key you put two new lines "\r\n\r\n".
实现自己的WebSockets协议肯定会带来一些好处和丰富的经验作为对自身协议的控制。但是你必须花一些时间来做这件事,并确保实施非常可靠。
Implementing own WebSockets protocol definitely have some benefits and great experience you get as well as control over protocol it self. But you have to spend some time doing it, and make sure that implementation is highly reliable.
同时你可以看看谷歌准备使用的解决方案(再次)足够了。
In same time you might have a look in ready to use solutions that google (again) have enough.
这篇关于创建“Hello World” WebSocket示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!