NodeJS 使用Socket.IO实例

    这篇文章是看国外的一篇博客写的,觉得国内的博客没有这篇写的这么深入浅出,所以决定翻译过来,让英文不好的童鞋们看起来更方便一些。只是按照原文大概的翻译哈。
原文链接:http://danielnill.com/nodejs-tutorial-with-socketio/
注:本示例是在node v6.2.0 和socket.io 1.4.8下写的,其他版本如果有运行不出来的请自行查看相关说明文档。

这篇文章要做什么

这篇博客会告诉你们怎么:
  • 搭建一个Node.JS 服务器以及路由(刚做web开发的我对路由在web服务器怎么实现不是很懂,看了这个一目了然 router)
  • 用socket.io和这个服务器连接
  • 从服务器发送数据到客户端
  • 从客户端发送数据到服务器

一个基础的服务器

    这个其实官网上就有例子,而且很简单。但是我还是跟着他从这里开始敲了。你会看到一个服务器从最简单是怎么开始的。当然,这里原文说有很多模块可以用来给socket.io搭建服务器,但是都大同小异。我们这里还是使用Node的http库,新建一个文件,重命名为server.js,敲入以下代码:
var http = require('http');
var server = http.createServer();
server.listen(8001);
    OK,到这里最简单的Node服务器就搭建起来了。在控制台里面cd到这个文件的文件夹,再使用命令node server.js,这个服务器就启动了。当然这时候你是看不到什么的,打开浏览器输入http://127.0.0.1:8001也不会看到什么东西。好吧,那可以在上面这段代码里面加一句话,说明这段代码运行了。像这样:
var http = require('http');
var server = http.createServer();
server.listen(8001);
console.log('服务器已经启动 地址:http://127.0.0.1:8001');
    这样你在控制台输入node server.js的时候就能够看到输出的信息了。或者你也可以写得更Node Style一点,像这样:
var http = require('http');
var server = http.createServer();
server.listen(8001, function(){
    console.log('服务器已经启动 地址:http://127.0.0.1:8001');
});
    但是我们打开浏览器还是什么都看不到,那么再来做一些修改,让它能够在浏览器输出一些文字:
var http = require('http');

var server = http.createServer(function(request, response){
    response.writeHead('Content-Type': 'text/html');
    response.write('Hello From Node');
    response.end();
});

server.listen(8001, function(){
    console.log('服务器已经启动 地址:http://127.0.0.1:8001');
});
    现在保存server.js然后在控制台node server.js,然后打开浏览器并在地址栏键入:http://127.0.0.1:8001然后就可以看到浏览器上显示了“Hello From Node”。
    每次我们访问http://127.0.0.1:8001的时候,在createServer里面的函数就会运行。传给createServer的参数是一个回调函数,会给浏览器响应,而我们这里的响应就是给浏览器发送一个字符串。

给服务器加上路由

    现在我们的服务器只能相应跟地址的请求,而其他路径是响应不到的,所以我们在这里改我们的server.js,给它加上路由:
var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(requset, response){
    var path = url.parse(request.url).pathname;

    switch(path){
        case '/':
            response.writeHead(200, {'Content-Type': 'text/html'});
            response.write('Hello From Node');
            response.end();
            break;
        case '/socket.html':
            fs.readFile(__dirname + path, function(error, data){
                if(error){
                    response.writeHead(404);
                    response.write("opps this doesn't exist - 404");
                    response.end();
                }
                else{
                    response.writeHead(200, {'Content-Type': "text/html"});
                    response.write(data, "utf-8");
                    response.end();
                }
            });
            break;
        default:
            response.writeHead(404);
            response.write("opps this doesn't exist - 404");
            response.end();
            break;
    }
});

server.listen(8001, function(){
    console.log('服务器已经启动 地址:http://127.0.0.1:8001');
});
    保存我们的server.js文件,然后运行node server.js。这时候打开浏览器,输入http://127.0.0.1:8001,和之前没有任何变化。好吧,不过如果你输入http://127.0.0.1:8001/socket.html,就会开到一个404页面,也就是说我们还没有socket.html这个文件。那么先来看看我们做了哪些改变:
var url = require('url');
var fs = require('fs');
    这两行代码,我们引入了两个新的模块,一个是url,一个是fs——file system。url模块是用来解析url的,更多更仔细的说明:[url参考文档](http://nodejs.org/docs/v0.3.1/api/url.html)。fs模块是用来操作文件的,它的说明:[fs模块参考文档](http://nodejs.org/api/fs.html)。
var path = url.parse(request.url).pathname;
    这行代码会把跟在根路径之后的地址赋给path。如果不清楚url.parse()这个函数是干嘛的,可以去查一查文档。所以说,如果输入的是http://www.baidu.com/。那么path就等于'/',如果输入http://127.0.0.1/socket.html,那么path就等于'/socket.html'。如果你想看看path到底等于什么,可以在这行下面加上console.log(path)。
    接下来的代码里,我们用了一个switch语句,用来根据path的值决定我们响应的方式。如果是http://127.0.0.1,也就是path是'/'的时候,还是会响应一个字符串:"Hello From Node",如果地址栏输入的是http://127.0.0.1/socket.html的话,就会把socket.html这个页面返回给浏览器。这里
fs.readFile(function(error, data){...});

是一个异步方法。如果读取成功,就会运行error里面的代码,如果成功,就把socket.html这个页面返回给客户端。
所以我们可以在server.js同一目录下新建一个socket.html文件,看看是否能够成功进到这里。

<html>
<head></head>
<body>这就是socket.html页面</body>
</html>

保存socket.html,确保server.js还在运行,在浏览器输入http://127.0.0.1:8001 就可以看到我们写的页面了。好了,到这里为止,我们已经给我们的服务器添加了路由。接下来就要加上socket.io模块了。

添加socket.io模块

    首先,当然是要安装socket.io的。如果你已经安装了npm的话,直接在你的server.js和socket.html的文件夹下,用命令npm install socket.io --save就可以了。如果你还没安装npm,请先安装npm。
    首先要引用这么模块,然后初始化之。我们的server.js现在看起来应该是这样。注意第四行和最后一行。
var http = require("http");
var url = require('url');
var fs = require('fs');
var io = require('socket.io');

var server = http.createServer(function(request, response){
    var path = url.parse(request.url).pathname;

    switch(path){
        case '/':
            response.writeHead(200, {'Content-Type': 'text/html'});
            response.write('hello world');
            response.end();
            break;
        case '/socket.html':
            fs.readFile(__dirname + path, function(error, data){
                if (error){
                    response.writeHead(404);
                    response.write("opps this doesn't exist - 404");
                    response.end();
                }
                else{
                    response.writeHead(200, {"Content-Type": "text/html"});
                    response.write(data, "utf8");
                    response.end();
                }
            });
            break;
        default:
            response.writeHead(404);
            response.write("opps this doesn't exist - 404");
            response.end();
            break;
    }
});

server.listen(8001);

io.listen(server);
    第四行是引入socket.io这个包,最后一行是说当这个服务器启动的时候,就给socket.io一个监听的实例。每当客户端有websocket请求的时候,就交给socket.io来处理。
    现在服务器已经做好处理websocket请求的准备了,但是客户端还没有做好准备,所以我们要修改我们的socket.html代码:
<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
  </head>
  <body>
    <script>
      var socket = io.connect();
    </script>
    <div>This is our socket.html file</div>
  </body>
</html>
    注意这里的<script src="/socket.io/socket.io.js"></script>并不是socket.io.js的相对地址,我也不知道什么机制就能够引用到的,baidu了一下,并没有确切答案,又不能FQ,反正这么写没毛病。
    这样就做好准备了,下面就要从服务器向客户端发送消息了。

从服务器向客户端发送消息

    现在的目标是要从服务器向客户端发送消息。所有的消息都通过socket.io发送,在浏览器也使用socket.io接收。我们用Node最常用的方式,用on来监听一个事件,用emit发送事件,这样就能够完成数据的发送和接收了。具体看代码。

server.js:

var http = require("http");
var url = require('url');
var fs = require('fs');
var io = require('socket.io');

var server = http.createServer(function(request, response){
    var path = url.parse(request.url).pathname;

    switch(path){
        case '/':
            response.writeHead(200, {'Content-Type': 'text/html'});
            response.write('hello world');
            response.end();
            break;
        case '/socket.html':
            fs.readFile(__dirname + path, function(error, data){
                if (error){
                    response.writeHead(404);
                    response.write("opps this doesn't exist - 404");
                    response.end();
                }
                else{
                    response.writeHead(200, {"Content-Type": "text/html"});
                    response.write(data, "utf8");
                    response.end();
                }
            });
            break;
        default:
            response.writeHead(404);
            response.write("opps this doesn't exist - 404");
            response.end();
            break;
    }
});

server.listen(8001);

var listener = io.listen(server);
listener.sockets.on('connection', function(socket){
    socket.emit('message', {'message': 'hello world'});
});
    这里我们在代码的最后面加上了事件的监听和发送。每次有一个客户端连上服务器的时候,都会有一个'connection'事件产生。在服务器接收到'connection'事件的时候,就会调用函数来想客户端发送一个json格式的消息:socket.emit('message',{'message','hello world'});。
    同样,在客户端我们也要进行相应的处理,才能够接收到服务器传来的数据。可以写成这样:

socket.html:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
  </head>
  <body>
    <script>
      var socket = io.connect();

      socket.on('message', function(data){
          console.log(data.message);
      });
    </script>
    <div>This is our socket.html file</div>
  </body>
</html>
    在客户端,我们也是用socket.on()来接收'message'消息的。下面的console.log()会在浏览器的控制台打印相应的字符串。现在重新运行server.js然后刷新你的页面,在浏览器按下F12,就可以看到控制台上面打印出来hello world了。这说明服务器已经成功向客户端发送消息。
    当然,我们可以做一点更有意思的事情,比如每一秒钟,向客户端发送一条消息。有一个函数是setInterval(),可以指定间隔多少毫秒做一件事情。所以,我们可以把server.js的代码改成:
server.listen(8001);

var listener = io.listen(server);
listener.sockets.on('connection', function(socket){
    //send data to client
    setInterval(function(){
        socket.emit('date', {'date': new Date()});
    }, 1000);
});

这样我们就每一秒钟给客户端发送当前的时间。当然,socket.html的代码也要做修改:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>  </head>
  <body>
    <script>
      var socket = io.connect();

      socket.on('date', function(data){
        $('#date').text(data.date);
      });
    </script>
    <div id="date"></div>
  </body>
</html>

这样再次运行,就会看到div里面显示的时间每秒钟跳一次。
这里有一点需要注意:引用jquery如果是使用本地的jquery.js文件的话,会出现404的错误。这是因为我们在设置路由的时候,如果不是’/socket.html’的路径,我们都把它转到404了,所以会找不到jquery.js文件。需要对路由稍作修改,就能够找到了。在switch里面加上:

switch(path){
    ...
    case '/jquery.js':
        fs.readFile(__dirname + path, function(error, data){
                if (error){
                    response.writeHead(404);
                    response.write("opps this doesn't exist - 404");
                    response.end();
                }
                else{
                    response.writeHead(200, {"Content-Type": "text/html"});
                    response.write(data, "utf8");
                    response.end();
                }
            });
        break;
    ...
}

从客户端向服务端发送消息

    从客户端向服务端发送消息的形式也差不多,只不过在客户端用socket.emit()然后在服务端用socket.on()接收。
    socket.html:
<html>
<head>
  <script src="/socket.io/socket.io.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
</head>
<body>
  <script>
  var socket = io.connect();
  socket.on('date', function(data){
    $('#date').text(data.date);
  });

  $(document).ready(function(){
    $('#text').keypress(function(e){
      socket.emit('client_data', {'letter': String.fromCharCode(e.charCode)});
    });
  });
  </script>
  <div id="date"></div>
  <textarea id="text"></textarea>
</body>
</html>

server.js:

var listener = io.listen(server);

listener.sockets.on('connection', function(socket){
  //send data to client
  setInterval(function(){
    socket.emit('date', {'date': new Date()});
  }, 1000);

  //recieve client data
  socket.on('client_data', function(data){
    process.stdout.write(data.letter);
  });
});

再次运行,在textarea中敲入字母,在控制台里面就能够看到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值