我正在尝试为浏览器输入交互的应用程序编写C#WebSocket服务器。
这是代码:
class Program {
static void Main(string[] args) {
var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 42001);
listener.Start();
using(var client = listener.AcceptTcpClient())
using(var stream = client.GetStream())
using(var reader = new StreamReader(stream))
using(var writer = new StreamWriter(stream)) {
while (!reader.EndOfStream) {
String line = reader.ReadLine();
if (new Regex("^GET").IsMatch(line)) {
line = reader.ReadLine();
if (new Regex("^Sec-WebSocket-Key: ").IsMatch(line)) {
String key = new Regex("(^Sec-WebSocket-Key\\: |\\r\\n)").Replace(line, "");
key = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));
writer.WriteLine("HTTP/1.1 101 Switching Protocols");
writer.WriteLine("Upgrade: websocket");
writer.WriteLine("Connection: Upgrade");
writer.WriteLine("Sec-WebSocket-Accept: " + key);
writer.WriteLine("Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits");
writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
writer.WriteLine("WebSocket-Location: ws://localhost:42001/websocket");
writer.WriteLine("");
}
}
}
}
listener.Stop();
}
}
......和:
var ws = new WebSocket('ws://localhost:42001/websocket');
ws.onopen = function() {
console.log('connected');
};
ws.onmessage = function(e) {
console.log(e.data);
};
ws.onerror = function(e) {
console.log(e);
};
ws.onclose = function() {
console.log("closed");
};
执行时,TPCListener成功接受TCPClient并读取传入的HTTP请求。它解析Key
,生成正确的Accept
令牌,但JS - window
本机 - WebSocket似乎已经消失了:无论收到什么,它都无法回答。
我希望它在发送HTTP/1.1 400 Bad Request
时会抛出错误,但一切都没有发生。它只是静音。
检查Chrome开发工具的Networking
标签,我只看到websocket传出的GET请求,但没有传入的数据包 - 应该发生什么?
如果我强行关闭应用程序,WebSocket会抛出此异常:
WebSocket connection to 'ws://localhost:42001/websocket' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
。
我在这里缺少什么?提前谢谢大家。
另外,我没有使用Net.WebSockets
因为它从.NET 4.5开始可用,我的应用程序将系统从Windows 7定位到当前版本的Windows 10。
答案 0 :(得分:1)
嗯......你的C#代码到底有多远?我的第一个赌注是缓冲 - 你没有刷新写入器或流,所以我会期望他们在卡住while
循环的顶部时保持数据,但是坦率地说,它首先不应该是while
循环 - 每个插槽只能获得一次握手,而不是很多。您可以尝试在空白行后添加刷新,并且应该确保Socket
本身已禁用缓冲(NoDelay = true;
) - 但是:从根本上说,这不是编写Web套接字服务器的好方法。除了其他任何事情,如果握手成功,数据将不再是文本,因此拥有TextReader
是一件非常糟糕的事情。坦率地说,你应该在这里处理原始Socket
/ byte[]
数据,IMO(已多次实现这一点)。