一、Html5WebSocket介绍

WebSocket protocol 是HTML5一种新的协议(protocol)。它是实现了浏览器与服务器全双工通信(full-duplex)。

现在,很多网站为了实现即时通讯(real-time),所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(time interval)(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request d的模式带来很明显的缺点 – 浏览器需要不断的向服务器发出请求(request),然而HTTP request 的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽。

而最比较新的技术去做轮询的效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求(reuqest)。

在 WebSocket API,浏览器和服务器只需要要做一个握手的动作(实际上是tcp),然后,浏览器和服务器之间就形成了一条快速通道(这里走的是新的协议)。两者之间就直接可以数据互相传送。

二、IM系统的几种通信方式

1.点对点通信(对等通信方式):客户端A想要与客户端B进行通信,首页会与IM服务器进行一次握手,然后从IM服务器拿到客户端B的地址。然后直接向客户端B发送消息,然后客户端B获取到A客户端的地址,也直接向客户端A回复消息,这样就不通过IM服务器来中转,这样双方的即时文字消息就不通过 IM服务器中转,而是通过网络进行点对点的直接通讯,这称为对等通讯方式(Peer To Peer) 。PS:这种方式需要做内网穿透或代理,不然无法获取到对方的地址等信息。

2.代理通信:当客户端A与客户端B之间存在防火墙,网速很慢等原因,IM服务器可以提供消息中专的服务,客户端A先把消息发送到IM服务器,然后再通过IM服务器把消息转发给客户端B,这样无需得到客户端的地址信息就能实现消息送达,这种方式叫做代理通信。

3.离线代理通信:当客户端A想要与客户端B通信的时候,发现客户端B不在线,这样IM服务器会把消息存起来,等到下一次客户端B上线的时候,由客户端B主动获取到离线消息(这样做好像可以降低服务器的压力)。

三、利用Html5的WebSocket实现简单的聊天室

1.服务端代码如下,注释那些都挺全的,就不一一多说:

 private async Task WebSocketContext(AspNetWebSocketContext context)
{
try
{
WebSocket socket = context.WebSocket; //获取连接信息
string user_name = TDCMS.Common.TD_Request.GetQueryStringValue("user_name", ""); //第一次open时,添加到连接池中
if (_userPool.Find(c => c.User_name== user_name) == null)
{
_userPool.Add(new UserPool() { User_name = user_name , Socket = socket });
}
else
{
UserPool p = _userPool.Find(c => c.User_name == user_name);
if (socket != p.Socket)//当前对象不一致,更新
{
p.Socket = socket;
}
} UserPool sourcePool= _userPool.Find(c => c.User_name == user_name);//获取到发送者连接池 #region 对所有连接池中广播 我上线了
foreach (var item in _userPool)
{
MessageModel model = new MessageModel()
{
Aim = item.User_name,
Contents = user_name + "上线了",
Source = sourcePool.User_name,
Status =
};
await item.Socket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonHelper.ObjectToJson(model))), WebSocketMessageType.Text, true, CancellationToken.None);
}
#endregion bool isNext = true;
while (isNext)
{
if (socket.State == WebSocketState.Open)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[]);
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None); #region 关闭Socket处理,删除连接池
if (socket.State != WebSocketState.Open)//连接关闭
{
if (_userPool.Find(c => c.User_name == user_name) != null)
_userPool.Remove(_userPool.Find(c => c.User_name == user_name));//删除连接池
//广播当前在线的用户 我下线了
foreach (var item in _userPool)
{
MessageModel offline = new MessageModel()
{
Aim = item.User_name,
Contents = user_name + "下线了",
Source = sourcePool.User_name,
Status =
};
await item.Socket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonHelper.ObjectToJson(offline))), WebSocketMessageType.Text, true, CancellationToken.None);
}
break;
} #endregion #region 如果连接没有关闭,处理发送过来的消息 MessageModel model=new MessageModel();
int messageCount = result.Count;
string messageStr= Encoding.UTF8.GetString(buffer.Array, , messageCount);
model = JsonHelper.JsonToObject<MessageModel>(messageStr);//这个是解析好的 消息 //发送消息到每个客户端
foreach (var item in _userPool)
{
await item.Socket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonHelper.ObjectToJson(model))), WebSocketMessageType.Text, true, CancellationToken.None);
} #endregion
}
} }
catch(Exception ex)
{
throw ex;
}
}

2.客户端JS代码如下:

 <script>
var im;//WebSocket对象
function initIm() {
var user=$('#txtUserName').val();
im = new MyIm(window.location.hostname, window.location.port, user);
$('.online').show();
$('.offline').hide();
im.Init();
} //创建一个对象 里面有3个方法,分别为Init:初始化Socket连接、Send:发送消息、Colse:关闭连接
var MyIm = function (path, prot, user_name) {
this.requestPath = 'ws://' + path + ':' + prot + '/tools/Handler.ashx';
this.user_name = user_name;
this.param = '?user_name=' + this.user_name;
this.socekt; }
MyIm.prototype = {
Init: function () {
this.socekt = new WebSocket(this.requestPath + this.param);
this.socekt.onopen = function () {
addSysMessage('连接成功','')
};//连接成功
this.socekt.onmessage = function (result) {
//这里返回的消息为json格式,里面的data为服务器返回的内容
var json = eval('(' + result.data + ')');
if (Number(json.Status) == ) {
addSysMessage(json.Contents,json.Time)
} else {
addMessage(json);
}
};//接收到消息的时候
this.socekt.onclose = function (result) {
addSysMessage('我的连接关闭了','')
}//连接关闭的时候
this.socekt.onerror = function (result) {
addSysMessage('网络发生了错误', '');//当这一步被执行时,close会被自动执行,所以无需主动去执行关闭方法
}//当连接发生错误的时候
},
Send: function (msg) {
//这里可以直接发送消息给服务器,但是为了让服务器好区分我的消息是属于通知还是普通消息还是其他,所以做成了json
//后台获取到json,解析后针对不同的消息类型进行处理
var json = '{"Status":0,"Contents":"'+msg+'","Source":"'+this.user_name+'","Aim":""}';
this.socekt.send(json);
},
Close: function () {
if (this.socekt != null) {
this.socekt.close();
return;
}
}
}
//把通知消息载入到通知列表
function addSysMessage(msg, time) {
if (time.length <= ) {
time = new Date();
}
$('.messageBox').append('<li><p class="time">' + time + '</p><p class=\"message\">' + msg + '</p></li>');
}
//把聊天消息载入到聊天框
function addMessage(json) {
$('.mainBox').append('<li><p class="time">' + json.Time + '</p><p class=\"message\"><span>'+json.Source+'说:</span>' + json.Contents + '</p></li>');
}
//发送消息
function sendMsg() {
var contents = $('#txtContents').val();
im.Send(contents);
}
//关闭连接
function offLine() {
im.Close(); $('.online').hide();
$('.offline').show();
}
</script>

3.客户端HTML:

<div class="mainIm">
<div>
<ul class="mainBox">
</ul>
<ul class="messageBox">
</ul>
</div>
<div class="online" style="display:none;">
<input type="text" id="txtContents" placeholder="输入要发送的内容" />
<input type="button" value="发送" onclick="sendMsg()" /><input type="button" value="断开连接" onclick="offLine()" />
</div>
<div class="offline">
<input type="text" id="txtUserName" placeholder="请输入一个用户名" />
<input type="button" value="连接" onclick="initIm()" />
</div>
</div>

4.最后的效果如下:

三、总结

目前IE并不支持WebSocket,就目前来说,这种方式并不适用于大范围使用。

这里只是实现了简单的聊天室,如果想要一对一,只需找到用户的连接池,向该连接池发送消息即可,如果用户不存在,可以创建一个全局变量离线消息池来储存离线消息。

如有大神发现写的不会的地方,请多多指教!!!

使用Html5下WebSocket搭建简易聊天室的更多相关文章

  1. php+websocket搭建简易聊天室实践

    1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...

  2. 基于Node.js + WebSocket 的简易聊天室

    代码地址如下:http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.js ...

  3. node.js+websocket实现简易聊天室

    (文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) websocket提供了一种全双工客户端服务器的异步通信方法,这种通信方法使用ws或者wss协议,可 ...

  4. node+websocket创建简易聊天室

    关于websocket的介绍太多,在这就不一一介绍了,本文主要实现通过websocket创建一个简易聊天室,就是90年代那种聊天室 服务端 1.安装ws模块,uuid模块,ws是websocket模块 ...

  5. Python开发【笔记】:aiohttp搭建简易聊天室

    简易聊天室: 1.入口main.py import logging import jinja2 import aiohttp_jinja2 from aiohttp import web from a ...

  6. 学习JavaSE TCP/IP协议与搭建简易聊天室

    一.TCP/IP协议 1.TCP/IP协议包括TCP.IP和UDP等 2.域名通过dns服务器转换为IP地址 3.局域网可以通过IP或者主机地址寻找到相应的主机 4.TCP是可靠的连接,效率低,且连接 ...

  7. nodejs+mongoose+websocket搭建xxx聊天室

    简介 本文是由nodejs+mongoose+websocket打造的一个即时聊天系统:本来打算开发一个类似于网页QQ类似功能的聊天系统,但是目前只是开发了一个模块功能 --- 类似群聊的,即一对多的 ...

  8. WebSocket实现简易聊天室

    前台页面: <html> <head> <meta http-equiv="Content-Type" content="text/html ...

  9. websocket搭建的聊天室

    在前后端数据交互的时候我们经常使用的是ajax,用的是传统的http协议,而http协议有个致命的缺点,就是请求一结束,连接就断开了, 我们为了保持这个链接的,通常会使用cookie,而自从h5出现w ...

随机推荐

  1. 使用EPPlus读写xlsx文件

    朋友有个需求,想对N张excel表做过滤和合并的处理,拜托我写个小程序.因为用户的背景是非专业用户,因此最好的选择是写个GUI程序,再加上读写excel的需求,所以我的首选就是C#的WinForm了. ...

  2. 老李分享:Web Services 架构 1

    老李分享:Web Services 架构   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9 ...

  3. 老李分享:qtp自动化测试框架赏析-关键字自动化测试框架

    老李分享:qtp自动化测试框架赏析-关键字自动化测试框架   QTP从2005年继winrunner,robot逐渐退出历史舞台之后,占领主流自动化测试工具市场已经10年之久.当初为了提高在自动化测试 ...

  4. 测试开发Python培训:模拟登录新浪微博-技术篇

    测试开发Python培训:模拟登录新浪微博-技术篇   一般一个初学者项目的起点就是登陆功能的自动化,而面临的项目不同实现的技术难度是不一样的,poptest在做测试开发培训中更加关注技术难点,掌握技 ...

  5. Sphinx安装流程及配合PHP使用经验

    1.什么是Sphinx Sphinx是俄罗斯人Andrew Aksyonoff开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行. 全文检索式指以文档的全部文本信息作为检索对象的一种信息检 ...

  6. Android常用adb命令

    1.进入手机命令行模式 adb shell 有多部手机的话 adb -s + 手机编号 + shell 2.安装apk adb install 然后将apk文件拖进命令行 卸载apk adb unin ...

  7. java 基础知识一 初识java

    java  基础知识一初识java 1.java语言的特点 (1)简洁有效(2)可移植性(3)面向对象(4)解释型(5)适合分布式计算 2.java的源文件扩展名为.java 编译后的扩展名为.cla ...

  8. 一些IO流的知识

    IO流: 输入流:输出流: 字节流:字符流:为了处理文字数据方便而出现的对象. 其实这些对象的内部使用的还是字节流(因为文字最终也是字节数据) 只不过,通过字节流读取了相对应的字节数,没有对这些字节直 ...

  9. 免费给自己的网站加 HTTPS

    简介 本文是通过 Let's Encrypt 提供的免费证书服务,实现让自己的网站加上 HTTPS.我的网站 -- hellogithub,就是通过这种方式实现的 HTTPS,效果如下: Let's ...

  10. 在Oracle中添加用户登录名称

    第一步,打开Oracle客户端单击 “帮助”-->"支持信息"-->”TNS名“,加入红色部分.页面如下: 第二步,再次打开Oracle客户端时,就会显示数据库了,只需 ...