服務器端源碼:web
76號協議增長了加密字段後端
sec-websocket-key1服務器
sec-websocket-key2websocket
以及最後8個字節socket
服務器必須在握手信息以後發送回解密信息才能握手成功。ui
解密方式加密
key1 是 sec-websocket-key1 後面全部字節spa
key2 是 sec-websocket-key2 後面全部字節orm
part1 爲 key1內除去全部的非數字字符後獲得的數字 long型 / key1內空字符長度 int型ip
part2 爲 key2內除去全部的非數字字符後獲得的數字 long型 / key1內空字符長度 int型
part1 轉換爲byte[] byte1 (例:byte1 = {1,2,3,4})
part2 轉換爲byte[] byte2
byte一、byte2內值倒轉(例:byte1 = {4,3,2,1})
byte3 是 客戶端發送過來的最後8個字節
byte一、byte二、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(); } } }}