C# websocket Server 加密 76号协议
服务器端源码:
76号协议增加了加密字段
sec-websocket-key1
sec-websocket-key2
以及最后8个字节
服务器必须在握手信息之后发送回解密信息才能握手成功。
解密方式
key1 是 sec-websocket-key1 后面所有字节
key2 是 sec-websocket-key2 后面所有字节
part1 为 key1内除去所有的非数字字符后得到的数字 long型 / key1内空字符长度 int型
part2 为 key2内除去所有的非数字字符后得到的数字 long型 / key1内空字符长度 int型
part1 转换为byte[] byte1 (例:byte1 = {1,2,3,4})
part2 转换为byte[] byte2
byte1、byte2内值倒转(例:byte1 = {4,3,2,1})
byte3 是 客户端发送过来的最后8个字节
byte1、byte2、byte3 拼装为16个字节 byteKey[16]
byteKey[] 进行 MD5 加密 得 byteMD5[]
byteMD5[] 放置在握手协议最后端发送回去
C# cs:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Web.Security;
using System.IO;
namespace Room
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("服务器启动中...");
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("192.168.1.80"), 2000);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ipe);
socket.Listen(60);
Console.WriteLine("服务器启动完毕...");
bool isfirst = true;
bool run = true;
try
{
Socket a = socket.Accept();
while (run)
{
byte[] bytes = new byte[1024];
int bytelength = a.Receive(bytes);
Console.WriteLine("接收完毕。");
#region websocket握手
if (isfirst)
{
string recStr = Encoding.UTF8.GetString(bytes, 0, bytelength);
string[] ss = recStr.Split(Environment.NewLine.ToCharArray());
string k1 = ss[10].Substring(20);
string k2 = ss[12].Substring(20);
byte[] last = new byte[8];
for (int i = 0; i < 8; i++)
{
last[i] = bytes[bytelength - 8 + i];
}
uint key1 = (uint)(long.Parse(FilterNonNumber(k1)) / FilterNonEmpty(k1).Length);
uint key2 = (uint)(long.Parse(FilterNonNumber(k2)) / FilterNonEmpty(k2).Length);
byte[] byteTemp1 = BitConverter.GetBytes(key1);
byte[] byteKey1 = new byte[4];
byte[] byteTemp2 = BitConverter.GetBytes(key2);
byte[] byteKey2 = new byte[4];
for (int i = 0; i < 4; i++)
{
byteKey1[i] = byteTemp1[3 - i];
byteKey2[i] = byteTemp2[3 - i];
}
MemoryStream ms = new MemoryStream();
ms.Write(byteKey1, 0, 4);
ms.Write(byteKey2, 0, 4);
ms.Write(last, 0, 8);
ms.Flush();
byte[] byteMs = ms.ToArray();
ms.Dispose();
MD5 md5 = MD5.Create();
byte[] md = md5.ComputeHash(byteMs);
MemoryStream ms1 = new MemoryStream();
string sendStr = "HTTP/1.1 101 WebSocket Protocol Handshake/r/nUpgrade: WebSocket/r/nConnection: Upgrade/r/nSec-WebSocket-Origin: null/r/nSec-WebSocket-Location: ws://192.168.1.80:2000//r/n/r/n";
byte[] temp = Encoding.UTF8.GetBytes(sendStr);
ms1.Write(temp, 0, temp.Length);
ms1.Write(md, 0, md.Length);
ms1.Flush();
byte[] byteSend = ms1.ToArray();
ms1.Dispose();
a.Send(byteSend, byteSend.Length, 0);
Console.WriteLine("发送完毕。");
isfirst = false;
}
#endregion
else
{
if (bytelength > 2)
{
string recStr = Encoding.UTF8.GetString(bytes, 1, bytelength - 2);
MemoryStream ms2 = new MemoryStream();
string strSend = "发送回去的是中文。";
byte[] byteSend = Encoding.UTF8.GetBytes(strSend);
ms2.WriteByte(0);
ms2.Write(byteSend, 0, byteSend.Length);
ms2.WriteByte(255);
ms2.Flush();
a.Send(ms2.ToArray());
ms2.Dispose();
if (recStr.Equals("exit"))
{
run = false;
Console.WriteLine("用户已退出。");
}
else
{
Console.WriteLine("接收到:" + recStr);
}
}
else
{
run = false;
Console.WriteLine("用户已退出。");
}
}
}
Console.ReadLine();
a.Close();
socket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
socket.Close();
}
}
public static string FilterNonNumber(string str)
{
if (str == null)
{
return "";
}
char[] c = str.ToCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0, len = c.Length; i < len; i++)
{
if (char.IsNumber(c[i]))
{
sb.Append(c[i]);
}
}
return sb.ToString();
}
public static string FilterNonEmpty(string str)
{
if (str == null)
{
return " ";
}
char[] c = str.ToCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0, len = c.Length; i < len; i++)
{
if (c[i] == ' ')
{
sb.Append(c[i]);
}
}
if (sb.ToString().Length == 0)
{
return " ";
}
else
{
return sb.ToString();
}
}
}
}