一、概述
WebSocket 协议是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信。
二、HTML5+NodeJs实现WebSocket即时通讯
参考:http://www.cnblogs.com/axes/p/3586132.html
准备知识:
-
服务器端语言:nodeJs(类似PHP)
-
nodeJs 管理包工具 npm(类似composer)
步骤1:安装nodejs
步骤2:安装npm(淘宝镜像http://npm.taobao.org并定制命令cnpm)
步骤3:在cmd运行初始化命令: npm init
步骤4:安装nodeJs的模块nodejs-websocke,运行命令:cnpm install nodejs-websocket
步骤5:将websocket包的监听js代码放到test.js,包网站:https://www.npmjs.com/package/nodejs-websocket
步骤6:运行node test.js
步骤7:打开game1、game2
三、基于Swoole的websocket
web聊天UI
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>聊天会话</title>
<style>
#content .left{
text-align: left;
}
#content .right{
text-align: right;
}
</style>
</head>
<body>
<div id="cc" style="width:700px;">
发送用户id:<input type="text" name="user" >
接收用户id:<input type="text" name="to_user" >
<button class="login">登录</button>
<div id="content" style=" height:400px; overflow:auto; width:100%; border:1px solid #ccc;"></div>
<form id="form">
<textarea id="texts" style="width:100%; height:200px;"></textarea>
<input type="button" onclick="ab();" value="发送">
</form>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
var uid,toUid;
$('.login').on('click' , function(){
uid = $('[name=user]').val().trim();
toUid = $('[name=to_user]').val().trim();
if(uid == '' || toUid == ''){
alert('请先登录');
}else{
aa(uid ,toUid );
}
})
var socket;
function aa(uid , toUid )
{
socket=new WebSocket('ws://192.168.82.31:9502?uid=' + uid );
socket.onopen=function()
{
console.log('用户id:' , uid);
var msg = setMsg(1 , '链接成功' , uid , toUid ) ;
console.log(msg);
socket.send( msg );
}
socket.onmessage=function(msg)
{
$('#content').append('<p class="b left"> '+msg.data+'</p>');
}
socket.onclose= function()
{
$('#content').append('<p class="c">退出聊天室</p>');
}
}
function ab()
{
var msg = $('#texts').val();
var sendmsg = setMsg( 2 , msg , uid , toUid );
socket.send( sendmsg );
$('#content').append('<p class="b right">'+msg+': 我(uid:'+uid+')</p>');
$('#texts').val('');
}
function az()
{
socket.close();
socket=null;
}
function setMsg( type , msg , uid ,toUid ){
var msgObject = {
type : type ,
msg: msg ,
uid: uid ,
to_uid: toUid
}
return JSON.stringify(msgObject);
}
</script>
</body>
</html>
服务端开启监听websocket事件
<?php
// server.php
// 所有登录用户的fd
$userFdList = [];
//创建websocket服务器对象,监听0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);
//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) use (&$userFdList) {
$userFdList[$request->get['uid']] = $request->fd ;
//var_dump($request);
//var_dump($request->fd, $request->get, $request->server);
$ws->push($request->fd, "系统:hello, welcome\n");
// echo '所有正在连接的用户:';
// print_r($userFdList);
});
//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) use (&$userFdList) {
echo '所有正在连接的用户:';
print_r($userFdList);
echo 'Message:<pre>';
$data = json_decode($frame->data , true);
print_r($data);
if($data['type'] == 1){
$ws->push($userFdList[$data['uid']], "系统:{$data['msg']}");
} else if( !isset($userFdList[$data['to_uid']])) {
$ws->push($userFdList[$data['uid']], "系统:用户没上线");
} else {
$ws->push($userFdList[$data['to_uid']], "别人(uid:{$data['uid']}):{$data['msg']}");
}
});
//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) use (&$userFdList) {
foreach ($userFdList as $key => $value) {
if( $value == $fd ) unset($userFdList[$key]);
}
echo "client-{$fd} is closed\n";
});
$ws->start();
- 在服务端开启监听:php server.php ;( php必须支持swoole )
- 在浏览器登录账号: