基于WebSocketSharp 的IM 简单实现
websocket-sharp 是一个websocket的C#实现,支持.net 3.5及以上来开发服务端或者客户端。本文主要介绍用websocket-sharp来做服务端、JavaScript做客户端来实现一个简单的IM。
WebSocketBehavior
WebSocketBehavior是核心对象,他包含了OnOpen,OnMessage,OnClose,OnError四个方法以及一个Sessions对象。熟悉websocket的都知道前四个方法是用来处理客户端链接、发送消息、链接关闭以及出错。sessions就是用来管理所有的回话连接。每产生一个连接,都会有一个新Id,sessions中会新增一个IWebSocketSession对象。当页面关闭或者刷新都会触发OnClose,继而sessions中会移除对应的IwebSocketSession对象。
WebSocketSessionManager 有一个广播方法:Sessions.Broadcast,通知所有连接的客户端。而WebSocketBehavior中的Send相当于是单发,只能将消息发送到此刻连接的一个客户端。摸清了以上这些我们就可以做一个简单的IM了。
Websoket.Server
新建一个C#控制台程序。现在Nugget中添加websocket-sharp.已经JSON。
然后新增一个Chat类,继承WebSocketBehavior,Chat相当于是一个websocket的服务,你可以创建多个websocketBehavior的实例然后在挂载在websocketServer上。
- public class Chat : WebSocketBehavior
- {
- private Dictionary<string,string> nameList=new Dictionary<string, string>();
- protected override async Task OnMessage(MessageEventArgs e)
- {
- StreamReader reader = new StreamReader(e.Data);
- string text = reader.ReadToEnd();
- try
- {
- var obj = Json.JsonParser.Deserialize<JsonDto>(text);
- Console.WriteLine("收到消息:" + obj.content + " 类型:" + obj.type + " id:" + Id);
- switch (obj.type)
- {
- //正常聊天
- case "":
- obj.name = nameList[Id];
- await Sessions.Broadcast(Json.JsonParser.Serialize(obj));
- break;
- //修改名称
- case "":
- Console.WriteLine("{0}修改名称{1}",nameList[Id],obj.content);
- Broadcast(string.Format("{0}修改名称{1}", nameList[Id], obj.content),"");
- nameList[Id] = obj.content;
- break;
- default:
- await Sessions.Broadcast(text);
- break;
- }
- }
- catch (Exception exception)
- {
- Console.WriteLine(exception);
- }
- //await Send(text);
- }
- protected override async Task OnClose(CloseEventArgs e)
- {
- Console.WriteLine("连接关闭" + Id);
- Broadcast(string.Format("{0}下线,共有{1}人在线", nameList[Id], Sessions.Count), "");
- nameList.Remove(Id);
- }
- protected override async Task OnError(WebSocketSharp.ErrorEventArgs e)
- {
- var el = e;
- }
- protected override async Task OnOpen()
- {
- Console.WriteLine("建立连接"+Id);
- nameList.Add(Id,"游客"+Sessions.Count);
- Broadcast(string.Format("{0}上线了,共有{1}人在线", nameList[Id],Sessions.Count), "");
- }
- private void Broadcast(string msg, string type = "")
- {
- var data= new JsonDto(){content = msg,type = type,name = nameList[Id]};
- Sessions.Broadcast(Json.JsonParser.Serialize(data));
- }
- }
JsonDto
- class JsonDto
- {
- public string content { get; set; }
- public string type { get; set; }
- public string name { get; set; }
- }
这里用nameList来管理所有的链接Id和用户名称的对应关系,新上线的人都默认为游客。然后再OnMessage中定义了三种消息类型。1表示正常聊天,2表示修改名称。3表示系统通知。用来让前端做一些界面上的区分。
然后在Program中启动WebSocketServer。下面指定了8080端口。
- public class Program
- {
- public static void Main(string[] args)
- {
- var wssv = new WebSocketServer(null,);
- wssv.AddWebSocketService<Chat>("/Chat");
- wssv.Start();
- Console.ReadKey(true);
- wssv.Stop();
- }
- }
Client
html:
- <div id="messages">
- </div>
- <input type="text" id="content" value=""/>
- <button id="sendbt">发送</button>
- <div>昵称:<input type="text" id="nickName" /> <button id="changebt">修改</button> </div>
js:
- function initWS() {
- ws = new WebSocket("ws://127.0.0.1:8080/Chat");
- ws.onopen = function (e) {
- console.log("Openened connection to websocket");
- console.log(e);
- };
- ws.onclose = function () {
- console.log("Close connection to websocket");
- // 断线重连
- initWS();
- }
- ws.onmessage = function (e) {
- console.log("收到",e.data)
- var div=$("<div>");
- var data=JSON.parse(e.data);
- switch(data.type){
- case "1":
- div.html(data.name+":"+data.content);
- break;
- case "2":
- div.addClass("gray");
- div.html("修改名称"+data.content)
- break;
- case "3":
- div.addClass("gray");
- div.html(data.content)
- break;
- }
- $("#messages").append(div);
- }
- }
- initWS();
- function sendMsg(msg,type){
- ws.send(JSON.stringify({content:msg,type:type}));
- }
- $("#sendbt").click(function(){
- var text=$("#content").val();
- sendMsg(text,"1")
- $("#content").val("");
- })
- $("#changebt").click(function(){
- var text=$("#nickName").val();
- sendMsg(text,"2")
- })
运行效果:
是不是很方便~~,喜欢就赞一个。
源码:https://files.cnblogs.com/files/stoneniqiu/websocket-sharp.zip
websocket-sharp:http://sta.github.io/websocket-sharp/
nodejs 实现websocket服务端:http://www.cnblogs.com/stoneniqiu/p/5402311.html
基于WebSocketSharp 的IM 简单实现的更多相关文章
- 【微信支付】分享一个失败的案例 跨域405(Method Not Allowed)问题 关于IM的一些思考与实践 基于WebSocketSharp 的IM 简单实现 【css3】旋转倒计时 【Html5】-- 塔台管制 H5情景意识 --飞机 谈谈转行
[微信支付]分享一个失败的案例 2018-06-04 08:24 by stoneniqiu, 2744 阅读, 29 评论, 收藏, 编辑 这个项目是去年做的,开始客户还在推广,几个月后发现服务器已 ...
- 基于ThinkPHP框架的简单的后台管理系统
版权声明:本文为博主原创文章,未经博主允许不得转载. 基于ThinkPHP框架的简单的后台管理系统 一个简单的后台管理系统,可能还不全面,可以自己改,有登录功能 实例如图:
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...
- C++模板实现动态顺序表(更深层次的深浅拷贝)与基于顺序表的简单栈的实现
前面介绍的模板有关知识大部分都是用顺序表来举例的,现在我们就专门用模板来实现顺序表,其中的很多操作都和之前没有多大区别,只是有几个比较重要的知识点需要做专门的详解. #pragma once #inc ...
- 基于vue.js的简单用户管理
功能描述:添加.修改.搜索过滤 效果图: <!DOCTYPE html> <html lang="en"> <head> <title&g ...
- 基于Gecko内核的简单浏览器实现
分享一个基于Gecko内核的简单浏览器实现过程. 项目需要需要开发一个简单浏览器,由于被访问的网页中有大量Apng做的动画,使用IE内核的webbrowser不能播放,使用基于WebKit和Cefsh ...
- 基于django的自定义简单session功能
基于django的自定义简单session功能 简单思路: 1.建立自定义session数据库 2.登入时将用户名和密码存入session库 3.将自定义的随机session_id写入cookie中 ...
- 基于链路的OSPF简单口令认证
实验要求:掌握基于链路的OSPF简单口令认证 拓扑如下: 配置如下: R1enable configure terminal interface s0/0/0ip address 192.168.1. ...
- 基于ThinkPHP3.23的简单ajax登陆案例
本文将给小伙伴们做一个基于ThinkPHP3.2.的简单ajax登陆demo.闲话不多说.直接进入正文吧. 可能有些小伙伴认为TP自带的跳转页面挺好,但是站在网站安全的角度来说,我们不应该让会员看到任 ...
随机推荐
- python环境搭建--pycharm的安装及使用
学习网址: --菜鸟教程(2.0和3.0) http://www.runoob.com/python/python-tutorial.html http://www.runoob.com/python ...
- 实现iota函数
void Reverse(char *s) { char temp; char *p = s; char *q = s; while (*p != '\0') { p ++; } q --; whil ...
- 2018-01-28-TF源码做版本兼容的一个粗暴方法
layout: post title: 2018-01-28-TF源码做版本兼容的一个粗暴方法 key: 20180128 tags: IT AI TF modify_date: 2018-01-28 ...
- nodejs建立websocket通信
依赖模块 nodejs-websocket 服务端 const ws = require('nodejs-websocket'); console.log('开始建立连接...'); const se ...
- python3的zip函数
zip函数接受任意多个可迭代对象作为参数,将对象中对应的元素打包成一个tuple,然后返回一个可迭代的zip对象. 这个可迭代对象可以使用循环的方式列出其元素 若多个可迭代对象的长度不一致,则所返回的 ...
- 使用zii.widgets.CDetailView显示内容
Yii里的CDetailView可以用来显示详细内容,有时会遇到显示的html内容是被转义过的,也就是原本是要显示html样式的,结果显示出来的内容却是把html当作普通文本了. 先看一个CDetai ...
- python小白之路
阅读目录: 第一章:计算机基础 计算机硬件.操作系统.网络协议 第二章:python基础 初识python.常量变量.输入输出运算符.条件与循环语句.数字与字符串.列表与字典.元组与集合.阶段小测.字 ...
- 【OCR技术系列之四】基于深度学习的文字识别(3755个汉字)
上一篇提到文字数据集的合成,现在我们手头上已经得到了3755个汉字(一级字库)的印刷体图像数据集,我们可以利用它们进行接下来的3755个汉字的识别系统的搭建.用深度学习做文字识别,用的网络当然是CNN ...
- POJ 2404 Jogging Trails [DP 状压 一般图最小权完美匹配]
传送门 题意:找一个经过所有边权值最小的回路,$n \le 15$ 所有点度数为偶则存在欧拉回路,直接输出权值和 否则考虑度数为奇的点,连着奇数条边,奇点之间走已经走过的路移动再走没走过的路 然后大体 ...
- 【STL】c++ priority_queue的使用方法
最开始在项目文档看到priority_queue这个模板时,还以为是自己定义的呢,后来查了一下,原来这是STL中存在的一种优先队列. 1.最简单的使用方法 std::priority_queue< ...