1
下面我已詳細分享了我的代碼。我閱讀文檔和關於握手的一切。我遵循了文檔中提供的所有步驟以及互聯網上的衆多示例,但仍然存在此問題。奇怪的事情id websocket.onclsose()在我關閉服務器時被觸發。從服務器發送響應握手後,websocket.onopen不會觸發
// Simple Websocket server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
namespace WebSocketServer
{
class Program
{
//port
private static int _port = 8181;
static void Main(string[] args)
{
TcpListener t = new TcpListener(IPAddress.Loopback, _port);
t.Start();
Console.WriteLine("Server is started and waiting for client\n\n");
byte[] buff = new byte[255];
NetworkStream stream;
TcpClient client;
while(true)
{
client = t.AcceptTcpClient();
if (!client.Connected)
return;
// I need form a proper mechanism to get all the data out of network stream.
// If I wait too long client get disconnected and we dont get stream and if
// if we dont wait at all then data doesnt reach server port and hence cant
// read the handshake.
stream = client.GetStream();
while ((stream.Read(buff, 0, buff.Length)) != 0)
{
break;
}
if (0 != buff.Length)
break;
}
StreamWriter writer = new StreamWriter(stream);
writer.AutoFlush = true;
//while (stream.DataAvailable)
//stream.Read(buff, 0, buff.Length);
Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(buff));
string clientHandshake = System.Text.ASCIIEncoding.ASCII.GetString(buff);
char[] separators = new char[1];
separators[0] = '\n';
string[] temp = clientHandshake.Split(separators, 100);
string keyword = "Sec-WebSocket-Key";
string key = "";
foreach (string s in temp)
{
if (s.Contains(keyword))
{
string keyTemp= s.Substring(keyword.Length + 2);
key = keyTemp.Remove(keyTemp.Length - 1);
break;
}
}
string responseKey = GetServerResponseKey(key);
// Send Server handshake
string handshake =
"HTTP/1.1 101 Switching Protocols\r\n" +
"Upgrade: websocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Accept: " + responseKey + "\r\n";
writer.Write(handshake);
writer.Flush();
Console.WriteLine(handshake);
while ((stream.Read(buff, 0, buff.Length)) != 0)
{
break;
}
Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(buff));
// Keep Server alive
while (true)
{ }
}
//Helper method to convert string into Byte[]
private static byte[] GetByteArray(string str)
{
UTF8Encoding encoding = new UTF8Encoding();
return encoding.GetBytes(str);
}
//This method is requuired because it combines key(got it from client)
//with GUID. Then takes SHA1 hash of that string and then encode to base64.
//This is all required because Handshake mechanism can be done by only this
//way according to Websocket Protocol(http://datatracker.ietf.org/doc/rfc6455/)
private static string GetServerResponseKey(string key)
{
Console.WriteLine("original key = " + key);
string keyForHash = String.Concat(key, Guid.NewGuid());
Console.WriteLine("text version of server response key = " + keyForHash);
UTF8Encoding encoding = new UTF8Encoding();
byte[] temp = encoding.GetBytes(keyForHash);
SHA1 hashProvider = new SHA1CryptoServiceProvider();
byte[] keyForBase64 = hashProvider.ComputeHash(temp);
return Convert.ToBase64String(keyForBase64);
}
}
}
// Simple WebSocket Client
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebSocketClient._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
<script language="javascript" type = "text/javascript">
var ws;
function btnConnectSend_onclick() {
if ("WebSocket" in window) {
ws = new WebSocket("ws://localhost:8181");
ws.onopen = function() {
alert("Connection Open");
ws.send("Hello Server");
};
ws.onmessage = function(evt) {
form1.txtMessage.value = evt.data;
alert("Server says:" + evt.data);
};
ws.onclose = function() {
alert("Socket Closed!!!");
};
ws.onerror = function() {
alert("WTF!");
};
}
}
function btnClose_onclick() {
ws.close();
};
</script>
</head>
<body>
<form id="form1" runat="server">
<div style="height: 350px">
<input id="btnConnectSend" type="button" value="Connect/Send" onclick ="return btnConnectSend_onclick()"/>
<br />
<input id="txtMessage" type="text"/>
<br />
<input id="btnClose" type="button" value="Close" onclick="return btnClose_onclick()"/>
</div>
</form>
</body>
</html>
so sorry simonc我有那些在握手結束時仍然存在問題。我在試驗時評論他們。我會更新來源。不管怎麼說,多謝拉。 –
說明:客戶端握手中沒有任何Sec-WebSocket-Protocol頭。客戶握手是這樣的: GET /演示HTTP/1.1 升級:WebSocket的 連接:升級 主機:本地主機:8181 產地:HTTP://本地主機:64784 二段的WebSocket密鑰:Pa6n/e6GEVasIDbwIHvoMQ == 仲的WebSocket-版本:13 我的服務器響應是這樣的: HTTP/1.1 101交換協議 升級:WebSocket的 連接:升級 仲的WebSocket-接受:t5oQWBbjgYLIn7mF54q77iGCNq0 = –
感謝您的澄清。我已經更新了我的答案,並提供了關於我發現的另一個問題的說明。希望這個會爲你覆蓋一些東西。 – simonc