WebSocket服务端 C#示例代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Text.RegularExpressions;
using System.Security.Cryptography; namespace WebSocketDemo
{
class Program
{
static void Main(string[] args)
{
int port = ;
byte[] buffer = new byte[]; IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try
{
listener.Bind(localEP);
listener.Listen(); Console.WriteLine("等待客户端连接....");
Socket sc = listener.Accept();//接受一个连接
Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接...."); //握手
int length = sc.Receive(buffer);//接受客户端握手信息
sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));
Console.WriteLine("已经发送握手协议了...."); //接受客户端数据
Console.WriteLine("等待客户端数据....");
length = sc.Receive(buffer);//接受客户端信息
string clientMsg = AnalyticData(buffer, length);
Console.WriteLine("接受到客户端数据:" + clientMsg); //发送数据
string sendMsg = "您好," + clientMsg;
Console.WriteLine("发送数据:“" + sendMsg + "” 至客户端....");
sc.Send(PackData(sendMsg)); Console.WriteLine("演示Over!"); }
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/// <summary>
/// 打包握手信息
/// </summary>
/// <param name="secKeyAccept"></param>
/// <returns></returns>
private static byte[] PackHandShakeData(string secKeyAccept)
{
var responseBuilder = new StringBuilder();
responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
//如果把上一行换成下面两行,才是thewebsocketprotocol-17协议,但居然握手不成功,目前仍没弄明白!
//responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine);
//responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine); return Encoding.UTF8.GetBytes(responseBuilder.ToString());
} /// <summary>
/// 生成Sec-WebSocket-Accept
/// </summary>
/// <param name="handShakeText">客户端握手信息</param>
/// <returns>Sec-WebSocket-Accept</returns>
private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)
{
string handShakeText = Encoding.UTF8.GetString(handShakeBytes, , bytesLength);
string key = string.Empty;
Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
Match m = r.Match(handShakeText);
if (m.Groups.Count != )
{
key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
}
byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
return Convert.ToBase64String(encryptionString);
} /// <summary>
/// 解析客户端数据包
/// </summary>
/// <param name="recBytes">服务器接收的数据包</param>
/// <param name="recByteLength">有效数据长度</param>
/// <returns></returns>
private static string AnalyticData(byte[] recBytes, int recByteLength)
{
if (recByteLength < ) { return string.Empty; } bool fin = (recBytes[] & 0x80) == 0x80; // 1bit,1表示最后一帧
if (!fin)
{
return string.Empty;// 超过一帧暂不处理
} bool mask_flag = (recBytes[] & 0x80) == 0x80; // 是否包含掩码
if (!mask_flag)
{
return string.Empty;// 不包含掩码的暂不处理
} int payload_len = recBytes[] & 0x7F; // 数据长度 byte[] masks = new byte[];
byte[] payload_data; if (payload_len == )
{
Array.Copy(recBytes, , masks, , );
payload_len = (UInt16)(recBytes[] << | recBytes[]);
payload_data = new byte[payload_len];
Array.Copy(recBytes, , payload_data, , payload_len); }
else if (payload_len == )
{
Array.Copy(recBytes, , masks, , );
byte[] uInt64Bytes = new byte[];
for (int i = ; i < ; i++)
{
uInt64Bytes[i] = recBytes[ - i];
}
UInt64 len = BitConverter.ToUInt64(uInt64Bytes, ); payload_data = new byte[len];
for (UInt64 i = ; i < len; i++)
{
payload_data[i] = recBytes[i + ];
}
}
else
{
Array.Copy(recBytes, , masks, , );
payload_data = new byte[payload_len];
Array.Copy(recBytes, , payload_data, , payload_len); } for (var i = ; i < payload_len; i++)
{
payload_data[i] = (byte)(payload_data[i] ^ masks[i % ]);
} return Encoding.UTF8.GetString(payload_data);
} /// <summary>
/// 打包服务器数据
/// </summary>
/// <param name="message">数据</param>
/// <returns>数据包</returns>
private static byte[] PackData(string message)
{
byte[] contentBytes = null;
byte[] temp = Encoding.UTF8.GetBytes(message); if (temp.Length < )
{
contentBytes = new byte[temp.Length + ];
contentBytes[] = 0x81;
contentBytes[] = (byte)temp.Length;
Array.Copy(temp, , contentBytes, , temp.Length);
}
else if (temp.Length < 0xFFFF)
{
contentBytes = new byte[temp.Length + ];
contentBytes[] = 0x81;
contentBytes[] = ;
contentBytes[] = (byte)(temp.Length & 0xFF);
contentBytes[] = (byte)(temp.Length >> & 0xFF);
Array.Copy(temp, , contentBytes, , temp.Length);
}
else
{
// 暂不处理超长内容
} return contentBytes;
}
}
}

HTML5 客户端示例代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSockets客户端示例</title>
</head>
<script>
var webSocket;
function connect()
{
try
{
var readyState = new Array("正在连接","已建立连接","正在关闭连接","已关闭连接");
var host = "ws://localhost:10";
webSocket = new WebSocket(host);
var message = document.getElementById("message");
message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
webSocket.onopen = function()
{
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
webSocket.onmessage = function(msg)
{
message.innerHTML +="<p>接收信息:" + msg.data + "</p>";
}
webSocket.onclose=function()
{
message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
}
catch(exception)
{
message.innerHTML += "<p>有错误发生</p>";
}
}
function send()
{
var text = document.getElementById("text").value;
var message = document.getElementById("message");
if(text == "")
{
message.innerHTML += "<p>请输入一些文字</p>";
return ;
}
try
{
webSocket.send(text);
message.innerHTML += "<p>发送数据:" +text + "</p>";
}
catch(exception)
{
message.innerHTML += "<p>发送数据出错</p>";
}
document.getElementById("text").value="";
}
function disconnect()
{
webSocket.close();
}
</script>
<body>
<h1>WebSocket客户端示例</h1>
<div id="message"></div>
<p>请输入一些文字</p>
<input id="text" type="text">
<button id="connect" onClick="connect();">建立连接</button>
<button id="send" onClick="send();">发送数据</button>
<button id="disconnect" onClick="disconnect();">断开连接</button>
</body>
</html>

GitHub地址:BMBH/.NET-Demo

C# WebSocket模拟发送接收的更多相关文章

  1. C# Socket模拟发送接收

    Socket简介 通过TCP/IP与仪器或设备通讯,在C#语言中,我们通常采用Socket.本项目是一个简单的Socket建立服务监听与Socket作为客户端请求的一个示例. 项目结构 客户端项目 S ...

  2. C#小爬虫,通过URL进行模拟发送接收数据

    public async Task<string> SendDataAsync(HttpMethod httpMethod, string requestUrl, HttpContent ...

  3. C# 模拟串口发送接收

    一.准备虚拟串口驱动工具 创建俩个虚拟串口,如图: 二.创建两个控制台程序 模拟串口的发送接收数据 1. 接收数据,代码如下: //遍历串行端口名称数组 foreach (string port in ...

  4. 十一、模拟扫码登录微信(用Django简单的布置了下页面)发送接收消息

    为了能够模拟登陆QQ,并获取信息.对扫码登录微信进行了分析.简单的用了一下Django将获取的信息映射到页面上.(python3+pycharm) 主要过程就是: 1.获取二维码 2.扫码登录(有三种 ...

  5. 38KHz,NEC红外模拟发送和接收程序

    /*************************************************************************************************/ ...

  6. nodejs与websocket模拟简单的聊天室

    nodejs与websocket模拟简单的聊天室 server.js const http = require('http') const fs = require('fs') var userip ...

  7. PHP模拟发送POST请求之一、HTTP协议头部解析

    WEB开发中信息基本全是在POST与GET请求与响应中进行,GET因其基于URL的直观,易被我们了解,可POST请求因其信息的隐蔽,在安全的同时,也给开发者们模拟发送带来了麻烦.接下来的几篇博文中,我 ...

  8. 安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制

    安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制 socket 连接采用流的方式进行发送接收数据,采用thread线程的方式. 什么是线程?  详细代码介 ...

  9. outlook 2016 for windows 每次刷新发送接收邮件会弹出登陆界面

    Q: outlook2016 for windows 每次刷新发送接收邮件会弹出登陆界面,office365 ProPlus 都是正常激活了,Word 和Excel都不存在此类问题 A: 排除用户的o ...

随机推荐

  1. day13----迭代器、生成器、枚举对象

    一.迭代器: 定义: (从装有多个值的容器中一次取出一个值给外界) 器:迭代器是个容器,包含多个值 迭代:循环反馈,从容器中一次取出一个值 迭代器不同于索引取值,但是也可以从容器对象中从前往后逐个返回 ...

  2. 学号 20175329 2018-2019-3《Java程序设计》第四周学习总结

    学号 20175329 2018-2019-3<Java程序设计>第四周学习总结 教材学习内容总结 第五章 上周学习的第四章是体现了数据的封装,本章第五章主要是体现出对象的另外两个方面的重 ...

  3. Python 中的 10 个常见安全漏洞,以及如何避免(上)

    简评:编写安全代码很困难,当你学习一个编程语言.模块或框架时,你会学习其使用方法. 在考虑安全性时,你需要考虑如何避免被滥用,Python 也不例外,即使在标准库中,也存在用于编写应用的不良实践.然而 ...

  4. 还是要习惯在linux环境下作Java开发

    要FQ 怎么在ubuntu上安装jdk 网址: https://www.youtube.com/watch?v=NZB3Iy7Lve4 需要网站:http://p.web.umkc.edu/pv6xc ...

  5. NCC Meetup 2018 Shanghai 活动小结(含PPT与视频)

    NCC Meetup 2018 上海的活动于2018年6月30日在微软上海港汇办公室进行.原本计划30人规模的小型活动,结果收到了逾60人的报名,其中大部均来到现场参加了活动. 本次活动得到了微软公司 ...

  6. 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?

    注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...

  7. Python_装饰器精讲_33

    from functools import wraps def wrapper(func): #func = holiday @wraps(func) def inner(*args,**kwargs ...

  8. 使用 Travis CI 实现项目的持续测试反馈

    [篇幅较长,10.15前补充完毕,如希望探索可直接移步Github仓库:https://github.com/SivilTaram/CITest] 在编程课中,我们可以使用成熟的在线评测系统来测试某个 ...

  9. 14-Requests+正则表达式爬取猫眼电影

    '''Requests+正则表达式爬取猫眼电影TOP100''''''流程框架:抓去单页内容:利用requests请求目标站点,得到单个网页HTML代码,返回结果.正则表达式分析:根据HTML代码分析 ...

  10. Average Sleep Time CodeForces - 808B (前缀和)

    It's been almost a week since Polycarp couldn't get rid of insomnia. And as you may already know, on ...