아래 코드를 자세히 설명했습니다. 나는 핸드 셰이크에 관한 문서와 모든 것을 읽었습니다. 내가 문서화하고 인터넷에서 수많은 예제에 주어진 모든 단계를 따라 갔지만 여전히 나는이 문제가있다. 이상한 것은 서버를 닫을 때 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>
죄송합니다. simonc 나는 악수가 끝나고 그 문제가있었습니다. 거기에 문제가있었습니다. 나는 실험하면서 그들을 주석 처리했다. 나는 근원을 새롭게 할 것이다. 어쨌든 고마워. –
설명 : 클라이언트 핸드 셰이크에 Sec-WebSocket-Protocol 헤더가 없습니다. GET/데모 HTTP/1.1 업그레이드 : 웹 소켓 연결 : 호스트를 업그레이드 : 로컬 호스트 : 8181 원산지 : HTTP : // localhost를 : 64,784 초 - 웹 소켓 - 키 : Pa6n/e6GEVasIDbwIHvoMQ의 == 을 클라이언트 핸드 셰이크는 다음과 같이 초 - 웹 소켓-버전 : 13 내 서버 응답은 다음과 같이 보았다 : HTTP/1.1 101 전환 프로토콜 업그레이드 : 웹 소켓 연결 : 업그레이드 초-WebSocket을 수락 다음 사항에 대한 t5oQWBbjgYLIn7mF54q77iGCNq0는 = –
감사합니다. 나는 내가 봤던 또 다른 문제에 대한 노트로 나의 대답을 업데이트했다. 잘하면이 하나가 당신을 위해 물건을 다룰 것입니다. – simonc