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();

}

}

}

}