C# WebSocket模拟发送接收
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>
C# WebSocket模拟发送接收的更多相关文章
- C# Socket模拟发送接收
Socket简介 通过TCP/IP与仪器或设备通讯,在C#语言中,我们通常采用Socket.本项目是一个简单的Socket建立服务监听与Socket作为客户端请求的一个示例. 项目结构 客户端项目 S ...
- C#小爬虫,通过URL进行模拟发送接收数据
public async Task<string> SendDataAsync(HttpMethod httpMethod, string requestUrl, HttpContent ...
- C# 模拟串口发送接收
一.准备虚拟串口驱动工具 创建俩个虚拟串口,如图: 二.创建两个控制台程序 模拟串口的发送接收数据 1. 接收数据,代码如下: //遍历串行端口名称数组 foreach (string port in ...
- 十一、模拟扫码登录微信(用Django简单的布置了下页面)发送接收消息
为了能够模拟登陆QQ,并获取信息.对扫码登录微信进行了分析.简单的用了一下Django将获取的信息映射到页面上.(python3+pycharm) 主要过程就是: 1.获取二维码 2.扫码登录(有三种 ...
- 38KHz,NEC红外模拟发送和接收程序
/*************************************************************************************************/ ...
- nodejs与websocket模拟简单的聊天室
nodejs与websocket模拟简单的聊天室 server.js const http = require('http') const fs = require('fs') var userip ...
- PHP模拟发送POST请求之一、HTTP协议头部解析
WEB开发中信息基本全是在POST与GET请求与响应中进行,GET因其基于URL的直观,易被我们了解,可POST请求因其信息的隐蔽,在安全的同时,也给开发者们模拟发送带来了麻烦.接下来的几篇博文中,我 ...
- 安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制
安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制 socket 连接采用流的方式进行发送接收数据,采用thread线程的方式. 什么是线程? 详细代码介 ...
- outlook 2016 for windows 每次刷新发送接收邮件会弹出登陆界面
Q: outlook2016 for windows 每次刷新发送接收邮件会弹出登陆界面,office365 ProPlus 都是正常激活了,Word 和Excel都不存在此类问题 A: 排除用户的o ...
随机推荐
- 域名打开没有加上“http://”,导致报错{"code":-32603,"message":"Cannot navigate to invalid URL"}
1.在robotframework中写用例 Open Browser 192.168.4.110:8880/jwzh Chrome 2.没有写http:// 3.导致报错 4.正确写法应该是 Op ...
- sklearn官网-多分类问题
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- Java多线程(五)——线程等待与唤醒
一.wait().notify().notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线程进 ...
- oracle impdp将导出用户的所有对象导入至另一个用户下,生成的触发器语句问题处理
问题产生的操作步骤及详细说明: 1)操作的数据库是oracle 11g,先通过命令将用户GAS_NEW的数据导出,命令语句如下: expdp GAS_NEW/GAS_NEW@ORCL schemas= ...
- UIToolBar - 官方文档
继承关系:UIToolBar -> UIView -> UIResponder -> NSObject. toolBar是一个工具栏,用于显示一个或多个按钮.其按钮叫做toolBar ...
- Chrome开发者工具应对页面跳转页面点击事件等实用干货
1.如何解决页面跳转 打开Preserve log即可 禁用页面缓存在右边的disable cache 2.如何监听页面点击 重要的是举一反三,看不懂英文去翻译!Mouse鼠标,click点击,,,, ...
- BZOJ1283 序列 网络流区间覆盖模型
就是区间覆盖模型的费用流版. 区间覆盖模型
- #Leetcode# 942. DI String Match
https://leetcode.com/problems/di-string-match/ Given a string S that only contains "I" (in ...
- FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (112503036) exceeds the configured
Message: FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUpload ...
- POJ_1185_炮兵阵地 dp+状态压缩
题目:炮兵阵地 链接:http://poj.org/problem?id=1185 解题思路: 首先用 int 来表示每一行的情况,比如说第一行是k1,那么[ k1&(k1>>2) ...