nodejs死亡笔记之socket.io那些事(附可用来撩妹的聊天功能)
2016-08-18 10:35
267 查看
我相信有很多人是看到撩妹才进来的,别急,我们要一步一步来。
现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客服端的浏览器,这种方式有一个很大的弊端,就是会占用很多的带宽。
最新的轮询效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。
使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。而且它为我们实现即时服务带来了两大好处:
节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。
推送信息:不需要客户端请求,服务器可以主动传送数据给客户端。
实现了websocket的浏览器:
有些迫不及待想撩妹的 很生气,不是讲socket.io么,你扯websocket干嘛。我只能给你个关爱智障的眼神-.-
socket.io的特点
易用性:socket.io封装了服务端和客户端,使用起来非常简单方便。
跨平台:socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。
自适应:它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。
体验socket.io
首先,创建一个项目,安装socket.io模块
接下来,新建一个test.js文件:
为什么要监听80端口呢?因为我懒得写3000。。。80是默认端口,可以不输入的。
接下来,注册一个事件:
connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。
当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件,它在客户端连接断开是触发,这时候我就知道用户已经离开了。
目前为止,我们已经搭建好了一个最简单的socket服务器,为了在浏览器中能够访问到我们的服务,我们还需要在服务端搭建一个简单的web服务器,让浏览器能够访问我们的客户端页面。
为了便捷,我们选用node.js中常用的express框架来实现web服务,示例如下:
服务端构建完毕,下面看一看客户端应该如何使用。
服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。
首先添加网页index.html,并在网页中引用客户端js文件
当然这样的客户端引用方式并不是必须的,我们也可以引用官方的cdn或者下载到本地的客户端文件。一般情况下推荐引用动态生成的客户端文件,因为这样客户端和服务端的版本可以保持一致,减少出错的几率。
当客户端成功加载socket.io客户端文件后会获取到一个全局对象io,我们将通过io.connect函数来向服务端发起连接请求。
connect函数可以接受一个url参数,url可以socket服务的http完整地址,也可以是相对路径,如果省略则表示默认连接当前路径。与服务端类似,客户端也需要注册相应的事件来捕获信息,不同的是客户端连接成功的事件是connect。
了解了客户端如何使用,下面我们创建网页index.html,并添加如下内容(保存):
页面添加完毕还要记得在服务端app.js中为它添加路由,让我们可以访问测试网页:
最后一步:通信
示例-客户端向服务端发送消息(index.html):
连接成功后,我们向服务端发送消息hello world!,还为socket注册了message事件,它是send函数对应的接收消息的事件,当服务端向客户端send消息时,我们就可以在message事件中接收到发送过来的消息。
服务端向客户端发送消息也可以通过send的方式,示例 - 服务端向客户端发送消息(app.js):
到现在为止,socket.io的基本用法就结束了,看起来蛮简单的,接下来,稍微提一下socket.io的其他用法及原理。
socket.io是如何发送消息的?
在socket.io中,emit函数用于发送数据,还记得在入门篇中,我们使用send的方式实现了信息的互发,其实send函数只是emit的封装,实际上还是使用了emit,且看send函数是如何实现的:
在send函数中,获取到原来的参数,并在原来的基础上插入了一个参数message,然后调用了emit函数。通过send函数的实现,我们也学会了emit函数的用法,它有连个参数,第一个参数是事件名称,在接收端注册该事件就可以接收到发送过去的信息,事件名称可以自由定义,在不同的场景下,我们可以定义不同的事件来接收消息。第二个参数才是发送的数据。了解清楚了工作原理,下面来将send替换成emit函数发送信息:
socket.io的命名空间
命名空间着实是一个非常实用好用的功能。我们可以通过命名空间,划分出不同的房间,在房间里的广播和通信都不会影响到房间以外的客户端。
那么如何创建房间呢?在服务端,通过of(“”)的方式来划分新的命名空间:
示例中,我们创建一个名为chat的房间,客户端可以通过如下方式连接到指定的房间:
虽然连接到指定的房间,但是我们也可以在服务端操作,自由的进出房间:
socket.io的广播消息
在实时应用中,广播是一个不可或缺的功能,socket.io提供两种服务端广播方式。
第一种广播方式可以称之为’全局广播’,顾名思义,全局广播就是所有连接到服务器的客户端都会受到广播的信息:
但是,在实际应用场景中,我们很多时候并不需要所有用户都收到广播信息,有的广播信息只发送给一部分客户端,比如某个房间里面的用户,那么可以使用如下方式:
当使用to()的方式广播信息时,只有该命名空间下的客户端才会收到广播信息,是不是很方便呢。
sockei.io的中间件
socket.io提供中间件功能,我们可以通过中间件来对请求进行预处理,比如身份验证:
示例中展示了通过中间件进行身份验证,当没有cookie的时候抛出异常。
socket.io传递参数的方法
在很多应用场景中,客户端发起连接请求时都需要传递参数,这些参数可能是身份验证、初始化设置等等,那么socket.io发起连接时如何传递参数呢?
由于connect函数发起连接的参数是一个url,你可能会想到把参数拼接到url上,如http://xxxx?xx=xxxx,但是很遗憾这样是行不通的,我们可以通过这样的方式来传递参数:
在服务端可以这样获取到传递的参数:
客户端传递的参数已经被解析成了一个json对象,这个对象就是_query。
好了,socket.io的讲解就到这里,接下来是大家最喜欢的撩妹环节。
2。假如socket.io模块
3。修改routes目录下的index.js:
4。在app.js中添加代码:
5。在www文件里添加代码
6。在public目录下创建chat.html:
7。在public/stylesheets目录下的style.css中添加:
目录结构:
之后就可以愉快的聊天了。启动服务,在浏览器中输入http://localhost:3000/chat.html,同时打开两个页面就可以聊天了。
如图:
项目代码放在github上:https://github.com/CleverFan/nodejsStudy/tree/master/expressTest/day03_socketio
ps 具体怎么撩妹我还没想好,你们自己想吧,哈哈哈哈哈
websocket简介
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客服端的浏览器,这种方式有一个很大的弊端,就是会占用很多的带宽。
最新的轮询效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。
使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。而且它为我们实现即时服务带来了两大好处:
节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。
推送信息:不需要客户端请求,服务器可以主动传送数据给客户端。
实现了websocket的浏览器:
Tables | Are |
---|---|
chrome | Supported in version 4+ |
Firefox | Supported in version 4+ |
Internet Explorer | Supported in version 10+ |
Opera | Supported in version 10+ |
Safari | Supported in version 5+ |
socket.io
Socket.IO是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。socket.io的特点
易用性:socket.io封装了服务端和客户端,使用起来非常简单方便。
跨平台:socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。
自适应:它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。
体验socket.io
首先,创建一个项目,安装socket.io模块
npm install socket.io
接下来,新建一个test.js文件:
var io = require('socket.io'); var io = require('socket.io')(80);//监听80端口
为什么要监听80端口呢?因为我懒得写3000。。。80是默认端口,可以不输入的。
接下来,注册一个事件:
io.on('connection',function(socket){ //连接成功... socket.on('disconnect',function(){ //用户已经离开... }); });
connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。
当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件,它在客户端连接断开是触发,这时候我就知道用户已经离开了。
目前为止,我们已经搭建好了一个最简单的socket服务器,为了在浏览器中能够访问到我们的服务,我们还需要在服务端搭建一个简单的web服务器,让浏览器能够访问我们的客户端页面。
为了便捷,我们选用node.js中常用的express框架来实现web服务,示例如下:
var express = require('express'); var app = express(); app.get('/',function(req,res){ res.status(200).send('欢迎学习nodejs!'); }); var server = require('http').createServer(app); var io = require('socket.io')(server); io.on('connection',function(socket){ }); server.listen(80);
服务端构建完毕,下面看一看客户端应该如何使用。
服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。
首先添加网页index.html,并在网页中引用客户端js文件
<script src="/socket.io/socket.io.js"></script>
当然这样的客户端引用方式并不是必须的,我们也可以引用官方的cdn或者下载到本地的客户端文件。一般情况下推荐引用动态生成的客户端文件,因为这样客户端和服务端的版本可以保持一致,减少出错的几率。
//官方CDN <script src="https://cdn.socket.io/socket.io-1.2.1.js"></script>
当客户端成功加载socket.io客户端文件后会获取到一个全局对象io,我们将通过io.connect函数来向服务端发起连接请求。
var socket = io.connect('/'); socket.on('connect',function(){ //连接成功 }); socket.on('disconnect',function(data){ //连接断开 });
connect函数可以接受一个url参数,url可以socket服务的http完整地址,也可以是相对路径,如果省略则表示默认连接当前路径。与服务端类似,客户端也需要注册相应的事件来捕获信息,不同的是客户端连接成功的事件是connect。
了解了客户端如何使用,下面我们创建网页index.html,并添加如下内容(保存):
<html> <head> <script src="/socket.io/socket.io.js"></script> <script> window.onload = function(){ var socket = io.connect('/'); socket.on('connect',function(){ document.write('连接成功!'); }); }; </script> </head> <body> </body> </html>
页面添加完毕还要记得在服务端app.js中为它添加路由,让我们可以访问测试网页:
app.get('/index',function(req,res){ res.sendFile('index.html',{root:__dirname}); });
最后一步:通信
示例-客户端向服务端发送消息(index.html):
var socket = io.connect('/'); socket.on('connect',function(){ //客户端连接成功后发送消息'hello world!' socket.send('hello world!'); }); socket.on('message',function(data){ alert(data); });
连接成功后,我们向服务端发送消息hello world!,还为socket注册了message事件,它是send函数对应的接收消息的事件,当服务端向客户端send消息时,我们就可以在message事件中接收到发送过来的消息。
服务端向客户端发送消息也可以通过send的方式,示例 - 服务端向客户端发送消息(app.js):
var io = require('scoket.io'); io.on('connection',function(socket){ socket.send('welcome!'); socket.on('message',function(data){ //收到消息 console.log(data); }); });
到现在为止,socket.io的基本用法就结束了,看起来蛮简单的,接下来,稍微提一下socket.io的其他用法及原理。
socket.io是如何发送消息的?
在socket.io中,emit函数用于发送数据,还记得在入门篇中,我们使用send的方式实现了信息的互发,其实send函数只是emit的封装,实际上还是使用了emit,且看send函数是如何实现的:
function send(){ var args = toArray(arguments); args.unshift('message'); this.emit.apply(this, args); return this; }
在send函数中,获取到原来的参数,并在原来的基础上插入了一个参数message,然后调用了emit函数。通过send函数的实现,我们也学会了emit函数的用法,它有连个参数,第一个参数是事件名称,在接收端注册该事件就可以接收到发送过去的信息,事件名称可以自由定义,在不同的场景下,我们可以定义不同的事件来接收消息。第二个参数才是发送的数据。了解清楚了工作原理,下面来将send替换成emit函数发送信息:
//app.js io.on('connection',function(socket){ socket.emit('message','连接成功!'); socket.on('message',function(data){ }); });
socket.io的命名空间
命名空间着实是一个非常实用好用的功能。我们可以通过命名空间,划分出不同的房间,在房间里的广播和通信都不会影响到房间以外的客户端。
那么如何创建房间呢?在服务端,通过of(“”)的方式来划分新的命名空间:
io.of('chat').on('connection',function(socket){ });
示例中,我们创建一个名为chat的房间,客户端可以通过如下方式连接到指定的房间:
var socket = io.connect('/chat');
虽然连接到指定的房间,但是我们也可以在服务端操作,自由的进出房间:
socket.join('chat');//进入chat房间 socket.leave('chat');//离开chat房间
socket.io的广播消息
在实时应用中,广播是一个不可或缺的功能,socket.io提供两种服务端广播方式。
第一种广播方式可以称之为’全局广播’,顾名思义,全局广播就是所有连接到服务器的客户端都会受到广播的信息:
socket.broadcast.emit('DATA',data);
但是,在实际应用场景中,我们很多时候并不需要所有用户都收到广播信息,有的广播信息只发送给一部分客户端,比如某个房间里面的用户,那么可以使用如下方式:
socket.broadcast.to('chat').emit('DATA',data);
当使用to()的方式广播信息时,只有该命名空间下的客户端才会收到广播信息,是不是很方便呢。
sockei.io的中间件
socket.io提供中间件功能,我们可以通过中间件来对请求进行预处理,比如身份验证:
io.use(function(socket, next){ if (socket.request.headers.cookie) return next(); next(new Error('Authentication error')); });
示例中展示了通过中间件进行身份验证,当没有cookie的时候抛出异常。
socket.io传递参数的方法
在很多应用场景中,客户端发起连接请求时都需要传递参数,这些参数可能是身份验证、初始化设置等等,那么socket.io发起连接时如何传递参数呢?
var socket = io.connect('/');
由于connect函数发起连接的参数是一个url,你可能会想到把参数拼接到url上,如http://xxxx?xx=xxxx,但是很遗憾这样是行不通的,我们可以通过这样的方式来传递参数:
var socket = io.connect('/',{ _query:'sid=123456' });
在服务端可以这样获取到传递的参数:
io.use(function(socket){ var query = socket.request._query; var sid = query.sid; });
客户端传递的参数已经被解析成了一个json对象,这个对象就是_query。
好了,socket.io的讲解就到这里,接下来是大家最喜欢的撩妹环节。
撩妹技巧之聊天的实现
1。创建一个express项目(方法还是那个方法)2。假如socket.io模块
3。修改routes目录下的index.js:
var express = require('express'); var router = express.Router(); var socket_io = require('socket.io'); router.get('/', function(req, res, next) { res.send('response'); }); router.prepareSocketIO = function (server) { var io = socket_io.listen(server); io.sockets.on('connection',function (socket) { socket.on('join',function (user) { socket.user = user; socket.emit('state','server',true); socket.broadcast.emit('state','server',user+"online"); }); socket.on('sendMsg',function (msg) { socket.emit('chat',socket.user,msg); socket.broadcast.emit('chat',socket.user,msg); }); }); } module.exports = router;
4。在app.js中添加代码:
app.ready=function(server){ routes.prepareSocketIO(server); }
5。在www文件里添加代码
app.ready(server);
6。在public目录下创建chat.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script src="/socket.io/socket.io.js"></script> <link href="/stylesheets/style.css" type="text/css" rel="stylesheet"> </head> <body> <div> <table id="content"> </table> </div> <table class="tool"> <tr> <td class="left"> <div id="textContent" contenteditable="true" type="text"></div> </td> <td> <button id="send">发送</button> </td> </tr> </table> <script> var socket = io.connect('http://127.0.0.1:3000'); var userName = "访客某某"; socket.on('connect', function () { userName = prompt("请输入你的姓名?") || userName; socket.emit('join', userName); }); socket.on('chat', function (user, data) { if (user === userName) { $('<tr class="align-right"><td><span><span class="msg">' + data + '</span>' + user + '</span></td></tr>').appendTo($('#content')); } else { $('<tr class="align-left"><td><span >' + user + '<span class="msg">' + data + '</span></span></td></tr>').appendTo($('#content')); } p.className = direct; }); $('#send').click(function () { var content = $('#textContent').html(); if (content = content.replace(" ", "")) { socket.emit('sendMsg', content); $('#textContent').html(""); } }); </script> </body> </html>
7。在public/stylesheets目录下的style.css中添加:
table { width: 100%; } table.tool { position: fixed; bottom: 0; left: 0; right: 0; padding: 10px; } #content { height: auto; padding: 10px; padding-bottom: 32px; } #content tr { margin-bottom: 10px; } #textContent { border: 1px solid grey; border-radius: 5px; padding: 6px; } .left { width: 88%; } #send { width: auto; padding: 2px 12px; line-height: 26px !important; border-radius: 5px; font-weight: bold; color: white; background-color: #ff4400; } tr.align-left td > span { float: left; } tr.align-left td > span span { display: inline-block; } tr.align-right td > span { float: right; } tr.align-right td > span span { display: inline-block; } span .msg { padding: 6px; background-color: #00B7FF; border: 1px solid #00B7ee; border-radius: 5px; } .timer { display: block; text-align: center; }
目录结构:
之后就可以愉快的聊天了。启动服务,在浏览器中输入http://localhost:3000/chat.html,同时打开两个页面就可以聊天了。
如图:
项目代码放在github上:https://github.com/CleverFan/nodejsStudy/tree/master/expressTest/day03_socketio
ps 具体怎么撩妹我还没想好,你们自己想吧,哈哈哈哈哈
相关文章推荐
- [Nodejs]初探nodejs学习笔记- 如何使用nodejs搭建简单的UDP聊天功能
- nodejs简单实现TCP服务器端和客户端的聊天功能示例
- 用nodejs实现聊天功能
- nodejs基于WS模块实现WebSocket聊天功能的方法
- 安卓聊天功能结构设计(一)
- nodejs使用RSS实现Ghost博客搜索功能
- 利用ratchet 和 ZeroMQ 实现即时(推送)聊天的功能
- 模仿微信语音聊天功能(1)项目介绍及自定义按钮实现
- nodejs(数据查询功能4)
- iOS - 给高仿微信添加直播聊天功能
- php 聊天一对一聊天功能源代码
- socket聊天功能
- Nodejs实现多房间简易聊天室功能
- Linux下p2p的聊天功能实现
- 体验腾讯微博聊天功能
- 用Application轻松实现在线客服(简单的QQ聊天功能)
- nodejs结合Socket.IO实现的即时通讯功能详解
- 一个用来计算整星期日期的功能代码
- Netty 实现聊天功能