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();
}
}
}
}
C# websocket Server 加密 76号协议的更多相关文章
- Microsoft SQL Server 数据库 错误号大全
panchzh :Microsoft SQL Server 数据库 错误号大全0 操作成功完成. 1 功能错误. 2 系统找不到指定的文件. 3 系统找不到指定的路径. 4 系统无法打开文件. 5 拒 ...
- GIN+GORILLA=A GOLANG WEBSOCKET SERVER
鉴于聊天已然成为大部分app的基础功能,而大部分app用户基数有没有辣么大,常用的聊天server架构如xmpp或者消息队列实现之类的用起来还挺麻烦的,有比较难跟网页端做交互,加之H5标准落地,所以w ...
- swoole之建立 websocket server
一.代码部分 <?php /** * 为什么用WebSocket? * HTTP的通信只能由客户端发起 * * WebSocket 协议是基于TCP的一种新的网络协议.实现了浏览器与服务器全双工 ...
- 查看SQL SERVER 加密存储过程,函数,触发器,视图
原文:查看SQL SERVER 加密存储过程,函数,触发器,视图 create PROCEDURE sp_decrypt(@objectname varchar(50))ASbeginset noc ...
- 使用Jetty搭建Java Websocket Server,实现图像传输
https://my.oschina.net/yushulx/blog/298140 How to Implement a Java WebSocket Server for Image Transm ...
- SQL Server 加密案例解析
一.概述 加密是一种安全措施,有时候甚至是法律要求.作为攻破Windows系统的最后一道防线,通过加密可以保证在没有密钥的情况下获取备份或者物理介质变得毫无意义. 二.概念 加密层次结构 加密层次结构 ...
- SpringBoot报错:Failed to load ApplicationContext(javax.websocket.server.ServerContainer not available)
引起条件: WebSocket+单元测试,单元测试报错! 解决方法: SpringBootTest增加webEnvironment参数. https://docs.spring.io/spring-b ...
- io.undertow.websockets.jsr.ServerWebSocketContainer cannot be cast to org.apache.tomcat.websocket.server.WsServerContainer
Caused by: java.lang.ClassCastException: io.undertow.websockets.jsr.ServerWebSocketContainer cannot ...
- SQL SERVER孤立帐号的处理
Step1:查询 Use KSHR_F23 Go exec sp_change_users_login @Action='Report' Go Step2:处理 Use KSHR_F23 Go exe ...
随机推荐
- (转)mysql账号权限密码设置方法
原文:http://www.greensoftcode.net/techntxt/2013410134247568042483 mysql账号权限密码设置方法 我的mysql安装在c:\mysql 一 ...
- EventBus vs Otto vs LiteEventBus
http://blog.chengyunfeng.com/?p=449 http://litesuits.com/
- 【LeetCode OJ】Triangle
Problem Link: http://oj.leetcode.com/problems/triangle/ Let R[][] be a 2D array where R[i][j] (j < ...
- java作业4
(一) 请查看String.equals()方法的实现代码,注意学习其实现方法.(发表到博客作业上) (二) 整理String类的Length().charAt(). getChars().rep ...
- 14、SQL基础整理(存储过程)
存储过程procedure(proc) 数据库—可编程性—存储过程 新建存储过程: create proc firstproc as select *from fenshu go 执行存储过程: 存储 ...
- WPF Step By Step 完整布局介绍
WPF Step By Step 完整布局介绍 回顾 上一篇,我们介绍了基本控件及控件的重要属性和用法,我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景,当 然这些都是本人在实际项目中的 ...
- 重学STM32---(四)
今天把定时器看了一遍,觉得很有必要把记下来时常看一看 定时器3初始化,很简单,开时钟,装载ARR,PSC寄存器就行了,想要开什么中断在DIER寄存器设置就行了(不过当时我花了很长时间,用寄存器真的不熟 ...
- 转:label标签的特殊用法
容易被忽略的label标签 原始作用 label标签是HTML原生的标签,其原始的作用参考这里 label 标签为 input 元素定义标注(标记). label 元素不会向用户呈现任何特殊效果.不过 ...
- 《单页Web应用--温故JavaScrpt》学习笔记整理
变量作用域,函数提升和执行环境对象 1. 变量作用域 在 JavaScript 中,变量 的 作用域 由 函数 限定,即:唯一能定义变量作用域的语块就是 函数. 变量 要么是全局的,要么是局部的. ...
- Mysql时间戳函数
1.转换为时间戳 select unix_timestamp('2013-07-15 10-06-07') 如果参数为空,则为当前时间 2.转换为时间 select from_unixtime(tim ...