为什么需要socket.io?
node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验,于是socket.io诞生。
var
http = require(
'http'
),
url = require(
'url'
),
fs = require(
'fs'
),
server;
server = http.createServer(
function
(req, res){
// your normal server code
var
path = url.parse(req.url).pathname;
switch
(path){
case
'/'
:
res.writeHead(200, {
'Content-Type'
:
'text/html'
});
res.write(
'<h1>Hello! Try the <a href="/index.html">Socket.io Test</a></h1>'
);
res.end();
break
;
case
'/index.html'
:
fs.readFile(__dirname + path,
function
(err, data){
if
(err)
return
send404(res);
res.writeHead(200, {
'Content-Type'
: path ==
'json.js'
?
'text/javascript'
:
'text/html'
})
res.write(data,
'utf8'
);
res.end();
});
break
;
default
: send404(res);
}
}),
send404 =
function
(res){
res.writeHead(404);
res.write(
'404'
);
res.end();
};
server.listen(8080);
var
io = require(
'socket.io'
).listen(server);
io.sockets.on(
'connection'
,
function
(socket){
console.log(
"Connection "
+ socket.id +
" accepted."
);
socket.on(
'message'
,
function
(message){
console.log(
"Received message: "
+ message +
" - from client "
+ socket.id);
});
socket.on(
'disconnect'
,
function
(){
console.log(
"Connection "
+ socket.id +
" terminated."
);
});
});
|
客户端编程模型
客户端编程也是相似的处理方式,连接服务器,交互信息。比如下面的index.html页面:
<!doctype html>
<html>
<head>
<title>Socket.io Test</title>
<script src=
"/json.js"
></script> <!--
for
ie -->
<script src=
"/socket.io/socket.io.js"
></script>
</head>
<body>
<script>
var
socket;
var
firstconnect =
true
;
function
connect() {
if
(firstconnect) {
socket = io.connect(
null
);
socket.on(
'message'
,
function
(data){ message(data); });
socket.on(
'connect'
,
function
(){ status_update(
"Connected to Server"
); });
socket.on(
'disconnect'
,
function
(){ status_update(
"Disconnected from Server"
); });
socket.on(
'reconnect'
,
function
(){ status_update(
"Reconnected to Server"
); });
socket.on(
'reconnecting'
,
function
( nextRetry ){ status_update(
"Reconnecting in "
+ nextRetry +
" seconds"
); });
socket.on(
'reconnect_failed'
,
function
(){ message(
"Reconnect Failed"
); });
firstconnect =
false
;
}
else
{
socket.socket.reconnect();
}
}
function
disconnect() {
socket.disconnect();
}
function
message(data) {
document.getElementById(
'message'
).innerHTML =
"Server says: "
+ data;
}
function
status_update(txt){
document.getElementById(
'status'
).innerHTML = txt;
}
function
esc(msg){
return
msg.replace(/</g,
'<'
).replace(/>/g,
'>'
);
}
function
send() {
socket.send(
"Hello Server!"
);
};
</script>
<h1>Socket.io Test</h1>
<div><p id=
"status"
>Waiting
for
input</p></div>
<div><p id=
"message"
></p></div>
<button id=
"connect"
onClick=
'connect()'
/>Connect</button>
<button id=
"disconnect"
onClick=
'disconnect()'
>Disconnect</button>
<button id=
"send"
onClick=
'send()'
/>Send Message</button>
</body>
</html>
|
1. 启动服务器还是交给node,打开命令行窗口,定位到server.js所在文件夹,输入node server.js启动服务器。
在上面的index.html中,注意这行:<script src="/socket.io/socket.io.js"></script>。如果不想使用本地的socket.io脚本,可以直接使用下面这个公开的脚本:
|
此外需要注意这行:socket = io.connect(null)。这里的null代表连接本地服务,可以换成"localhost",效果也是一样的。
2. 可以使用socket.io直接启动http服务。例如:
var
io = require(
'socket.io'
).listen(80);
io.sockets.on(
'connection'
,
function
(socket) {
io.sockets.emit(
'this'
, { will:
'be received by everyone'
});
});
|
3. socket.io可以直接通过send方法发送消息,使用message事件接收消息,例如:
//server.js
var
io = require(
'socket.io'
).listen(80);
io.sockets.on(
'connection'
,
function
(socket) {
socket.on(
'message'
,
function
() { });
});
//index.html
<script>
socket.on(
'connect'
,
function
() {
socket.send(
'hi'
);
socket.on(
'message'
,
function
(msg) {
// my msg
});
});
</script>
|
4. 发送和处理数据
两端可以互发事件,互发数据,相互通信。发送事件的代码为:socket.emit(action, data, function),其中action为事件的名称,data为数据,function为回调函数;处理事件代码 为:socket.on(action,function),如果emit发送的时候有数据data,则function中参数包含了这个数据。 socket.io除了发送和处理内置事件,如connect, disconnect, message。还允许发送和处理自定义事件,例如:
//服务端:
io.sockets.on(
'connection'
,
function
(socket) {
socket.emit(
'news'
, { hello:
'world'
});
socket.on(
'my other event'
,
function
(data) {
console.log(data);
});
});
//客户端:
<script src=
"/socket.io/socket.io.js"
></script>
<script>
socket.on(
'news'
,
function
(data) {
console.log(data);
socket.emit(
'my other event'
, { my:
'data'
});
});
</script>
|
5. 从上面可以看出来,发送数据的时候,send和emit是都可以使用的。只不过emit更是强化了自定义事件的处理。
6. 可以在服务端使用socket的get/set方法存储客服端的相关数据,例如:
//服务端
var
io = require(
'socket.io'
).listen(80);
io.sockets.on(
'connection'
,
function
(socket) {
socket.on(
'set nickname'
,
function
(name) {
socket.set(
'nickname'
, name,
function
() { socket.emit(
'ready'
); });
});
socket.on(
'msg'
,
function
() {
socket.get(
'nickname'
,
function
(err, name) {
console.log(
'Chat message by '
, name);
});
});
});
//客户端
<script>
socket.on(
'connect'
,
function
() {
socket.emit(
'set nickname'
, confirm(
'What is your nickname?'
));
socket.on(
'ready'
,
function
() {
console.log(
'Connected !'
);
socket.emit(
'msg'
, confirm(
'What is your message?'
));
});
});
</script>
|