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 简单实现的更多相关文章

  1. 【微信支付】分享一个失败的案例 跨域405(Method Not Allowed)问题 关于IM的一些思考与实践 基于WebSocketSharp 的IM 简单实现 【css3】旋转倒计时 【Html5】-- 塔台管制 H5情景意识 --飞机 谈谈转行

    [微信支付]分享一个失败的案例 2018-06-04 08:24 by stoneniqiu, 2744 阅读, 29 评论, 收藏, 编辑 这个项目是去年做的,开始客户还在推广,几个月后发现服务器已 ...

  2. 基于ThinkPHP框架的简单的后台管理系统

    版权声明:本文为博主原创文章,未经博主允许不得转载. 基于ThinkPHP框架的简单的后台管理系统 一个简单的后台管理系统,可能还不全面,可以自己改,有登录功能 实例如图:    

  3. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  4. C++模板实现动态顺序表(更深层次的深浅拷贝)与基于顺序表的简单栈的实现

    前面介绍的模板有关知识大部分都是用顺序表来举例的,现在我们就专门用模板来实现顺序表,其中的很多操作都和之前没有多大区别,只是有几个比较重要的知识点需要做专门的详解. #pragma once #inc ...

  5. 基于vue.js的简单用户管理

    功能描述:添加.修改.搜索过滤 效果图: <!DOCTYPE html> <html lang="en"> <head> <title&g ...

  6. 基于Gecko内核的简单浏览器实现

    分享一个基于Gecko内核的简单浏览器实现过程. 项目需要需要开发一个简单浏览器,由于被访问的网页中有大量Apng做的动画,使用IE内核的webbrowser不能播放,使用基于WebKit和Cefsh ...

  7. 基于django的自定义简单session功能

    基于django的自定义简单session功能 简单思路: 1.建立自定义session数据库 2.登入时将用户名和密码存入session库 3.将自定义的随机session_id写入cookie中 ...

  8. 基于链路的OSPF简单口令认证

    实验要求:掌握基于链路的OSPF简单口令认证 拓扑如下: 配置如下: R1enable configure terminal interface s0/0/0ip address 192.168.1. ...

  9. 基于ThinkPHP3.23的简单ajax登陆案例

    本文将给小伙伴们做一个基于ThinkPHP3.2.的简单ajax登陆demo.闲话不多说.直接进入正文吧. 可能有些小伙伴认为TP自带的跳转页面挺好,但是站在网站安全的角度来说,我们不应该让会员看到任 ...

随机推荐

  1. Django_上传图片和模版获取图片

    需求: 在Django中,上传图片,存入数据库中的文件的路径,而不是图片本身,也就是说,图片等数据静态文件都可以放到第三方服务器上,我想在把图片保存到Django本地项目中,并可以通过Django自带 ...

  2. 如何去掉ul标签的多余空白或多余大距离?

    在css中写入 ul{ margin:; padding:; list-style: none; } 让其内边距和外边距为0,列表样式为空

  3. 创建一个离线优先,数据驱动的渐进式 Web 应用程序

    原文地址:Build an offline-first, data-driven PWA 译文出自:我的个人博客 概述 在本文中,您将学习如何使用 Workbox 和 IndexedDB 创建离线优先 ...

  4. wstring操作与普通段字符操作对照表

    字符分类:   宽字符函数普通C函数描述   iswalnum()   isalnum()   测试字符是否为数字或字母   iswalpha()   isalpha()   测试字符是否是字母    ...

  5. awk解决实际问题例子

    awk很有用,就不说了,下面记录几个我遇到的例子,汇总 1 获得linux环境变量(ENVIRON) awk 'BEGIN{print ENVIRON["PATH"];}' /et ...

  6. linkin大话设计模式--常用模式总结

    linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...

  7. 我的踩坑之旅-代码不规范引发的“bug”

    今早公司上班,老大跟我说有一个服务老是上线,下线,问我啥情况.我回想了下我的项目部署,觉得不可能会出现这个问题呀.然后各种鼓捣,倒腾了一个早上,终于找出了罪魁祸首. 场景:我们的服务部署在亚马逊上.我 ...

  8. 华为交换机boot默认密码

    交换机系统启动bootrom时,在2秒内按下"CTRL+B",此处需要输入密码才能进入BOOTROM菜单.默认密码如下: 1. S9300 V100R006及其之前的版本:9300 ...

  9. Servlet 浅析

    在我们学习Servlet之前,有必要了解一下Web容器的工作模式 我们所有的请求其实都是先到达了web容器,然后才分发给已经注册好的Servlet 请求由Servlet的service方法调用doGe ...

  10. bat自动打包压缩实现

    1.引言 本文档的编辑目的是为了实bat脚本自动打包功能,包含包的名字命名,压缩文件内外层文件夹的名字:包含svn版本号等: 2.实现介绍 (1)获取svn号,生成批处理文件 写一个pak.bat文件 ...