C# WebSocket
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
.Net 4.5及以后的版本才提供对websocket的支持,若项目所基于的.Net版本低于.Net 4.5且高于.Net 3.5,不妨尝试采用开源库websocket-sharp。
GitHub路径如下:https://github.com/sta/websocket-sharp 和 https://github.com/statianzo/Fleck
下面引用到 Fleck 和 WebSocketSharpFork
客户端
/// <summary>
/// 客户端帮助类 作者:韩永健
/// </summary>
public class WebSocketClientHelper
{
public delegate void ActionEventHandler();
public delegate void MessageEventHandler(string message);
public delegate void ErrorEventHandler(Exception ex);
/// <summary>
/// 客户端打开连接时调用
/// </summary>
public event ActionEventHandler OnOpen;
/// <summary>
/// 客户端关闭连接时调用
/// </summary>
public event ActionEventHandler OnClose;
/// <summary>
/// 收到客户端信息时调用
/// </summary>
public event MessageEventHandler OnMessage;
/// <summary>
/// 执行错误时调用
/// </summary>
public event ErrorEventHandler OnError;
/// <summary>
/// 服务
/// </summary>
private WebSocket client;
/// <summary>
/// 服务URL
/// </summary>
public string ServerUtl { private set; get; }
/// <summary>
/// 是否重连
/// </summary>
public bool IsReConnection { set; get; }
/// <summary>
/// 重连间隔(毫秒)
/// </summary>
public int ReConnectionTime { set; get; }
public WebSocketClientHelper(string serverUtl)
{
this.ServerUtl = serverUtl;
client = new WebSocket(this.ServerUtl);
client.OnOpen += new EventHandler(client_OnOpen);
client.OnClose += new EventHandler<CloseEventArgs>(client_OnClose);
client.OnMessage += new EventHandler<MessageEventArgs>(client_OnMessage);
client.OnError += new EventHandler<ErrorEventArgs>(client_OnError);
}
public WebSocketClientHelper(string serverUtl, bool isReConnection, int reConnectionTime = 1000)
: this(serverUtl)
{
this.IsReConnection = isReConnection;
this.ReConnectionTime = reConnectionTime;
}
public void client_OnOpen(object sender, EventArgs e)
{
try
{
Console.WriteLine("Open!");
if (OnOpen != null)
OnOpen();
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
public void client_OnClose(object sender, CloseEventArgs e)
{
try
{
Console.WriteLine("Close!");
if (OnClose != null)
OnClose();
//掉线重连
if (IsReConnection)
{
Thread.Sleep(ReConnectionTime);
Start();
}
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
public void client_OnMessage(object sender, MessageEventArgs e)
{
try
{
Console.WriteLine("socket收到信息:" + e.Data);
if (OnMessage != null)
OnMessage(e.Data);
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
//else
// throw ex;
}
}
public void client_OnError(object sender, ErrorEventArgs e)
{
if (OnError != null)
OnError(e.Exception);
//记录日志
//掉线重连
if (IsReConnection)
{
Thread.Sleep(ReConnectionTime);
Start();
}
}
/// <summary>
/// 启动服务
/// </summary>
public void Start()
{
try
{
client.ConnectAsync();
}
catch (Exception ex)
{
//日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
/// <summary>
/// 关闭服务
/// </summary>
public void Close()
{
try
{
IsReConnection = false;
client.CloseAsync();
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
/// <summary>
/// 发送信息
/// </summary>
public void Send(string message)
{
try
{
client.Send(message);
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
/// <summary>
/// 发送信息
/// </summary>
public void Send(byte[] message)
{
try
{
client.Send(message);
}
catch (Exception ex)
{
//记录日志
if (OnError != null)
OnError(ex);
else
throw ex;
}
}
}
/// <summary>
/// WebSocket服务辅助类 作者韩永健
/// </summary>
public class WebSocketServerHelper
{
/// <summary>
/// 客户端信息
/// </summary>
public class ClientData
{
/// <summary>
/// IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 端口号
/// </summary>
public int Port { get; set; }
}
public delegate void ActionEventHandler(string ip, int port);
public delegate void MessageEventHandler(string ip, int port, string message);
public delegate void BinaryEventHandler(string ip, int port, byte[] message);
public delegate void ErrorEventHandler(string ip, int port, Exception ex);
/// <summary>
/// 客户端打开连接时调用
/// </summary>
public event ActionEventHandler OnOpen;
/// <summary>
/// 客户端关闭连接时调用
/// </summary>
public event ActionEventHandler OnClose;
/// <summary>
/// 收到客户端信息时调用
/// </summary>
public event MessageEventHandler OnMessage;
/// <summary>
/// 收到客户端信息时调用
/// </summary>
public event BinaryEventHandler OnBinary;
/// <summary>
/// 执行错误时调用
/// </summary>
public event ErrorEventHandler OnError;
/// <summary>
/// 服务
/// </summary>
private Fleck.WebSocketServer server;
/// <summary>
/// socket列表
/// </summary>
private Dictionary<string, IWebSocketConnection> socketList = new Dictionary<string, IWebSocketConnection>();
private List<ClientData> clientList = new List<ClientData>();
/// <summary>
/// 客户端ip列表
/// </summary>
public List<ClientData> ClientList
{
get
{
return clientList;
}
}
/// <summary>
/// 服务URL
/// </summary>
public string ServerUtl { private set; get; }
public WebSocketServerHelper(string serverUtl)
{
this.ServerUtl = serverUtl;
server = new Fleck.WebSocketServer(this.ServerUtl);
}
/// <summary>
/// 启动服务
/// </summary>
public void Start()
{
server.Start(socket =>
{
try
{
socket.OnOpen = () => SocketOpen(socket.ConnectionInfo.ClientIpAddress, socket.ConnectionInfo.ClientPort);
socket.OnClose = () => SocketClose(socket.ConnectionInfo.ClientIpAddress, socket.ConnectionInfo.ClientPort);
socket.OnMessage = message => SocketMessage(socket.ConnectionInfo.ClientIpAddress, socket.ConnectionInfo.ClientPort, message);
socket.OnBinary = message => SocketBinary(socket.ConnectionInfo.ClientIpAddress, socket.ConnectionInfo.ClientPort, message);
socket.OnError = ex => SocketError(socket.ConnectionInfo.ClientIpAddress, socket.ConnectionInfo.ClientPort, ex);
socketList.Add(socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort, socket);
ClientList.Add(new ClientData() { IP = socket.ConnectionInfo.ClientIpAddress, Port = socket.ConnectionInfo.ClientPort });
}
catch (Exception ex)
{
}
});
}
/// <summary>
/// Socket错误
/// </summary>
private void SocketError(string ip, int port, Exception ex)
{
Console.WriteLine("Error!" + ip + ":" + port + " " + ex);
socketList.Remove(ip + ":" + port);
ClientList.RemoveAll(m => m.IP == ip && m.Port == port);
if (OnError != null)
OnError(ip, port, ex);
//else
// throw ex;
}
/// <summary>
/// Socket打开连接
/// </summary>
private void SocketOpen(string ip, int port)
{
try
{
Console.WriteLine("Open!" + ip + ":" + port);
if (OnOpen != null)
OnOpen(ip, port);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// Socket关闭连接
/// </summary>
private void SocketClose(string ip, int port)
{
try
{
Console.WriteLine("Close!" + ip + ":" + port);
socketList.Remove(ip + ":" + port);
ClientList.RemoveAll(m => m.IP == ip && m.Port == port);
if (OnClose != null)
OnClose(ip, port);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// 接收到的信息
/// </summary>
private void SocketBinary(string ip, int port, byte[] message)
{
try
{
Console.WriteLine("socket收到信息:byte[]");
if (OnBinary != null)
OnBinary(ip, port, message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// 接收到的信息
/// </summary>
private void SocketMessage(string ip, int port, string message)
{
try
{
Console.WriteLine("socket收到信息:" + message + " " + ip + ":" + port);
if (OnMessage != null)
OnMessage(ip, port, message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// 发送信息(单客户端)
/// </summary>
public void Send(string ip, int port, string message)
{
try
{
socketList[ip + ":" + port].Send(message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// 发送信息(单客户端)
/// </summary>
public void Send(string ip, int port, byte[] message)
{
try
{
socketList[ip + ":" + port].Send(message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(ip, port, ex);
else
throw ex;
}
}
/// <summary>
/// 发送信息(所有客户端)
/// </summary>
public void SendAll(string message)
{
for (int i = ; i < socketList.Count; i++)
{
var item = socketList.ElementAt(i);
try
{
item.Value.Send(message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(item.Value.ConnectionInfo.ClientIpAddress, item.Value.ConnectionInfo.ClientPort, ex);
else
throw ex;
}
}
}
/// <summary>
/// 发送信息(所有客户端)
/// </summary>
public void SendAll(byte[] message)
{
for (int i = ; i < socketList.Count; i++)
{
var item = socketList.ElementAt(i);
try
{
item.Value.Send(message);
}
catch (Exception ex)
{
if (OnError != null)
OnError(item.Value.ConnectionInfo.ClientIpAddress, item.Value.ConnectionInfo.ClientPort, ex);
else
throw ex;
}
}
}
}
C# WebSocket的更多相关文章
- 漫扯:从polling到Websocket
Http被设计成了一个单向的通信的协议,即客户端发起一个request,然后服务器回应一个response.这让服务器很为恼火:我特么才是老大,我居然不能给小弟发消息... 轮询 老大发火了,小弟们自 ...
- 细说WebSocket - Node篇
在上一篇提高到了 web 通信的各种方式,包括 轮询.长连接 以及各种 HTML5 中提到的手段.本文将详细描述 WebSocket协议 在 web通讯 中的实现. 一.WebSocket 协议 1. ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- WebSocket - ( 一.概述 )
说到 WebSocket,不得不提 HTML5,作为近年来Web技术领域最大的改进与变化,包含CSS3.离线与存储.多媒体.连接性( Connectivity )等一系列领域,而即将介绍的 WebSo ...
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...
- Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!
随着HTML5 WebSocket技术的日益成熟与普及,我们可以借助WebSocket来更加方便地打通BS与CS -- 因为B/S中的WebSocket可以直接连接到C/S的服务端,并进行双向通信.如 ...
- Cowboy 开源 WebSocket 网络库
Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...
- 借助Nodejs探究WebSocket
文章导读: 一.概述-what's WebSocket? 二.运行在浏览器中的WebSocket客户端+使用ws模块搭建的简单服务器 三.Node中的WebSocket 四.socket.io 五.扩 ...
- 细说websocket - php篇
下面我画了一个图演示 client 和 server 之间建立 websocket 连接时握手部分,这个部分在 node 中可以十分轻松的完成,因为 node 提供的 net 模块已经对 socket ...
- webSocket and LKDBHelper的使用说明
socketket与lkdbhelper来处理数据 客户需求: 当我们有需要从自己的后台推送消息给我们的用户时,用户需要实时的接收到来自我们的推送消息.前提是没有使用第三方的推送框架,那么这个使用we ...
随机推荐
- python django连接错误
提示: connection.alias,django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0 ...
- 983. Minimum Cost For Tickets
网址:https://leetcode.com/problems/minimum-cost-for-tickets/ 参考:https://leetcode.com/problems/minimum- ...
- Ajax、Flash优缺点
Ajax的优势:1.可搜索性 2.开放性 3.费用 4.易用性 5.易于开发.可搜索性 普通的文本网页会更有利于SEO.文本内容是搜索引擎容易检索的,而繁琐的swf字节码却是搜索引擎不愿触及的.虽然G ...
- 刷题upupup【Java中HashMap、HashSet用法总结】
HashMap: 常用操作 1. containsKey() 判断HashMap是否包含key 2. containsValue() 判断HashMap是否包含“值为value”的元素 3. get( ...
- Maskrcnn遇到的坑
第一个要讲maskrcnn 中keras 升到2.1 然后 在线程问题上要把workers设置成1,是否使用线程设置成false 然后调用模型的时候要把模型和加载文件放到一个目录下
- log日志文件
单文件写 根据日志的等级是否写入,下面的一个例子就是等级为10,大于等于等级10的记录,小于的话就不记录,在创建之前先进行基本的日志格式配置 import logging logging.basicC ...
- MYSQL查询操作 详细
学习目标 1 掌握select查询所有字段.指定字段的数据 2 掌握消除重复行命令distinct 3 掌握as给字段.表起别名 4 掌握条件查询where后跟比较运算符.逻辑运算符的用法 5 掌握条 ...
- 利用IIS部署WEB网站以及解决CSS/JS不能显示问题
利用IIS部署WEB网站以及解决CSS/JS不能显示问题 转载声明:http://blog.sina.com.cn/s/blog_a001e5980101b4kt.html vs中正常IIS发布网站后 ...
- Python_Mix*函数名的使用以及第一类对象,闭包,迭代器,for循环的内部机制
一:函数名的应用(第一类对象) 函数名的命名规范和变量是一样的,函数名其实就是变量名, 0)函数名可以赋值给其他变量 def func(): #定义一个名为func的函数 print('my ange ...
- Oracle 11g 测试ogg中断之后,重新同步操作
测试ogg中断之后,重新同步操作 2018-06-07 17:11 779 1 原创 GoldenGate 本文链接:https://www.cndba.cn/leo1990/article/2839 ...