nodejs实现套接字服务功能详解


Posted in NodeJs onJune 21, 2018

本文实例讲述了nodejs实现套接字服务功能。分享给大家供大家参考,具体如下:

一、什么是套接字

1. 套接字允许一个进程他通过一个IP地址和端口与另一个进程通信,当你实现对运行在同一台服务器上的两个不同进程的进程间通信或访问一个完全不同的服务器上运行的服务时,套接字很有用。node提供的net模块,允许你既创建套接字服务器又创建可以连接到套接字服务器的客户端。

2. 套接字位于HTTP层下面并提供服务器之间的点对点通信。套接字使用套接字地址来工作,这是IP地址和端口的组合。在套接字连接中,有两种类型的点:一类是服务器,它监听连接;一类是客户端,它打开一个到服务器的连接。服务器和客户端都需要一个唯一的IP地址和端口的组合。

3. 套接字是HTTP模块的底层结构,如果你不需要处理如get何post的web请求,只需要点对点的传输数据,那么使用套接字就可以就能为你提供一个轻量级的解决方案和更多的控制。

二、net.Socket对象

1. Socket对象同时在套接字服务器和客户端套接字上创建,并允许数据在它们之间来回写入和读取。在套接字客户端,当你调用net.connect()net.createConnection()时,Socket对象在内部创建,这个对象是为了表示到服务器的套接字连接。使用Socket对象来监控连接,将数据发送到服务器并处理来自服务器的响应。在套接字服务器上,当客户端连接到服务器时,Socket对象被创建,并被传递到连接事件处理程序,这个对象是为了表示对客户端的套接字连接。      在NodeJS中有三种socket:TCPUDPUnix域套接字,主要介绍NodeJS中TCP的基本编程知识。

2. 创建一个Socket对象,可以使用以下方法:

//第一种方法,通过一个options参数
var SocketClient = net.connect(options, [connectionListener]);
var SocketClient = net.createConnection(options, [connectionListener]);
//第二种方法,通过接受port和host值作为直接的参数
var SocketClient = net.connect(port, [host], [connectionListener]);
var SocketClient = net.createConnection(port, [host], [connectionListener]);
//第三种方法,通过接受指定文件系统位置的path参数,这个位置是一个Unix套接字在创建Socket对象时使用的。
var SocketClient = net.connect(path, [connectionListener]);
var SocketClient = net.createConnection(path, [connectionListener]);

无论你使用哪种,都将返回一个Socket对象,唯一的区别在于接受的第一个参数,而最后一个参数都是当连接对服务器打开时执行的回调函数。而无论你使用net.connect还是net.createConncetion,它们的工作方式是完全相同的。

那么至于第一个参数,指定的选项为:

port:客户端应连接到的端口。此选项是必需的。
host:客户端应该连接到的服务器的域名或IP地址。默认为localhost
localAddress:客户端应该绑定的用于网络连接的本地IP地址。
allowHalfOpen:一个布尔值,如果为true,则表示当套接字的另一端发送一个FIN数据包时,该套接字将不会自动发送一个FIN数据包,从而使Duplex流的一半保持开放。默认为false

3. 一旦Socket对象被创建,它就提供了在连接到服务器的生命周期中发出的几个事件,如下:

connect:成功建立与服务器的连接时发出。回调函数不接受任何参数
data:在套接字上收到数据时发出。如果没有数据时间处理程序被连接,那么数据可能会丢失。回调函数必须接受一个buffer对象作为参数,它包含从套接字读取的数据的块。
end:当服务器通过发送一个FIN终止连接时发出。回调函数不接受任何参数
timeout:由于不活动,因此到服务器的连接超时时发出。
drain:当写缓冲区变为空时发出。你可以使用此事件截回被写入套接字中的数据流。回调函数不接受任何参数
error:在套接字连接上发生错误时发出。回调函数应该接受错误的唯一参数。
close:套接字已完全关闭时发出,它可能是由一个end()方法关闭的,或者因为发生错误而关闭。回调函数不接受任何参数

4. Socket对象还提供了可以访问以获得该对象的信息的几个属性:

bufferSize   当前已缓冲并等待写入套接字的流中的字节数
remoteAddress   套接字连接到的远程服务器的IP地址
remotePort    套接字连接到的远程服务器的端口
localAddress   远程客户端用于套接字连接的本地IP地址
localPort     远程客户端用于套接字连接的本地端口
byteRead     由套接字读取的字节数
byteWritten    由套接字写入的字节数

三、net.Server对象

可以使用net.Server对象创建一个TCP套接字服务器,并监听对它的连接,你将能够读取和写入数据。

要创建一个服务器独享,使用net.createServer()方法:

net.createServer([options],[connectListener])

其中,options是一个对象,指定创建套接字Server对象时要使用的选项,如allowHalfOpen,可以使一半的Duplex流保持开放,默认为false。connectLlistenerconnection事件的回调函数,它在接收到连接时被执行。

举例:

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
// 创建一个TCP服务器实例,调用listen函数开始监听指定端口
// 传入net.createServer()的回调函数将作为”connection“事件的处理函数
// 在每一个“connection”事件中,该回调函数接收到的socket对象是唯一的
net.createServer(function(sock) {
  // 我们获得一个连接 - 该连接自动关联一个socket对象
  console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);
  // 为这个socket实例添加一个"data"事件处理函数
  sock.on('data', function(data) {
    console.log('DATA ' + sock.remoteAddress + ': ' + data);
    // 回发该数据,客户端将收到来自服务端的数据
    sock.write('You said "' + data + '"');
  });
  // 为这个socket实例添加一个"close"事件处理函数
  sock.on('close', function(data) {
    console.log('CLOSED: ' +
      sock.remoteAddress + ' ' + sock.remotePort);
  });
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);

服务端也可以用稍不同的方式接受TCP连接,即显式处理"connection"事件:

var server = net.createServer();
server.listen(PORT, HOST);
console.log('Server listening on ' +
  server.address().address + ':' + server.address().port);
server.on('connection', function(sock) {
  console.log('CONNECTED: ' +
     sock.remoteAddress +':'+ sock.remotePort);
  // 其它内容与前例相同
});

上述两个例子只是写法不同,并无本质区别。

创建TCP客户端

现在让我们创建一个TCP客户端连接到刚创建的服务器上,该客户端向服务器发送一串消息,并在得到服务器的反馈后关闭连接。下面的代码描述了这一过程。

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
  console.log('CONNECTED TO: ' + HOST + ':' + PORT);
  // 建立连接后立即向服务器发送数据,服务器将收到这些数据
  client.write('I am Chuck Norris!');
});
// 为客户端添加“data”事件处理函数
// data是服务器发回的数据
client.on('data', function(data) {
  console.log('DATA: ' + data);
  // 完全关闭连接
  client.destroy();
});
// 为客户端添加“close”事件处理函数
client.on('close', function() {
  console.log('Connection closed');
});

再举个例子:

var net=require('net');
function getConnection(connName){
  var client=net.connect({port:8017,host:'127.0.0.1'},function(){
    console.log(connName+' connected: ');
    console.log(' local=%s:%s',this.localAddress,this.localPort);
    console.log( ' remote=%s:%s',this.remoteAddress,this.remotePort);
    this.setTimeout(500);
    this.setEncoding('utf8');
    this.on('data',function(data){
      console.log(connName+' From Server: '+data.toString());
      this.end();
    });
    this.on('end',function(){
      console.log(connName+' Client disnected');
    });
    this.on('error',function(err){
      console.log('Socket Error: ',JSON.stringify(err));
    });
    this.on('timeout',function(){
      console.log('Socket Time Out');
    });
    this.on('close',function(){
      console.log('Socket Closed');
    });
  });
  return client;
}
function writeData(socket,data){
  var success=!socket.write(data);
  if(!success){
    (function (socket,data){
      socket.once('drain',function(){
        writeData(socket,data);
      });
    })(socket,data);
  }
}
var example1=getConnection('example1');
var example2=getConnection('example2');
writeData(example1,'This is example1');
writeData(example2,'This is example2');
var server=net.createServer(function(client){
  console.log('Client connection: ');
  console.log(' local=%s:%s',client.localAddress,client.localPort);
  console.log( ' remote=%s:%s',client.remoteAddress,client.remotePort);
  client.setTimeout(500);
  client.setEncoding('utf8');
  client.on('data',function(data){
    console.log('Received data from client on port %d:%s',client.remotePort,data.toString());
    console.log(' Bytes received:'+data.toString());
    writeData(client,'Sending: '+data.toString());
    console.log(' Bytes sent: '+client.bytesWritten)
  });
  client.on('end',function(){
    console.log('Client disconnected');
    server.getConnections(function(err,count){
      console.log('Remaining Connections: '+count);
    });
  });
  client.on('error',function(err){
    console.log('Socket Error: '+JSON.stringify(err));
  });
  client.on('timeout',function(){
    console.log('Socket Time Out');
  });
});
server.listen(8017,function(){
  console.log('Server listening: '+JSON.stringify(server.address()));
  server.on('close',function(){
    console.log('Server Terminated');
  });
  server.on('error',function(err){
    console.log('Server Error: ',JSON.stringify(err));
  });
});

nodejs实现套接字服务功能详解

希望本文所述对大家nodejs程序设计有所帮助。

NodeJs 相关文章推荐
浅析Nodejs npm常用命令
Jun 14 NodeJs
nodejs6下使用koa2框架实例
May 18 NodeJs
详解nodejs的express如何自动生成项目框架
Jul 12 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 NodeJs
详解nodejs中express搭建权限管理系统
Sep 15 NodeJs
Nodejs+angularjs结合multiparty实现多图片上传的示例代码
Sep 29 NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 NodeJs
使用nodeJs来安装less及编译less文件为css文件的方法
Nov 20 NodeJs
nodejs发送http请求时遇到404长时间未响应的解决方法
Dec 10 NodeJs
详解nodejs 开发企业微信第三方应用入门教程
Mar 12 NodeJs
Nodejs实现用户注册功能
Apr 14 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 NodeJs
详解Nodejs mongoose
Jun 10 #NodeJs
详解NodeJs开发微信公众号
May 25 #NodeJs
nodejs express配置自签名https服务器的方法
May 22 #NodeJs
通过nodejs 服务器读取HTML文件渲染到页面的方法
May 17 #NodeJs
解决nodejs的npm命令无反应的问题
May 17 #NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 #NodeJs
对mac下nodejs 更新到最新版本的最新方法(推荐)
May 17 #NodeJs
You might like
php网站判断用户是否是手机访问的方法
2013/11/01 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
2014/04/30 PHP
thinkphp在模型中自动完成session赋值示例代码
2014/09/09 PHP
PHP数组去重比较快的实现方式
2016/01/19 PHP
php解决DOM乱码的方法示例代码
2016/11/20 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
2017/03/14 PHP
PHP实现的链式队列结构示例
2017/09/15 PHP
PHP定义字符串的四种方式详解
2018/02/06 PHP
DOMAssitant最新版 DOMAssistant 2.5发布
2007/12/25 Javascript
JavaScript的常见兼容问题及相关解决方法(chrome/IE/firefox)
2013/12/31 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
2014/01/09 Javascript
跟我学习javascript的for循环和for...in循环
2015/11/18 Javascript
AngularJS用户选择器指令实例分析
2016/11/04 Javascript
详解vue-Resource(与后端数据交互)
2017/01/16 Javascript
vue进行图片的预加载watch用法实例讲解
2018/02/07 Javascript
在vue中更换字体,本地存储字体非引用在线字体库的方法
2018/09/28 Javascript
[01:38]2018DOTA2亚洲邀请赛主赛事第二日现场采访 神秘商人痛陈生计不易
2018/04/05 DOTA
《Python之禅》中对于Python编程过程中的一些建议
2015/04/03 Python
Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法
2015/05/20 Python
Python实现简单的代理服务器
2015/07/25 Python
PyCharm在win10的64位系统安装实例
2017/11/26 Python
批量将ppt转换为pdf的Python代码 只要27行!
2018/02/26 Python
python3.5安装python3-tk详解
2019/04/26 Python
Pycharm运行加载文本出现错误的解决方法
2019/06/27 Python
python使用docx模块读写docx文件的方法与docx模块常用方法详解
2020/02/17 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
Django查询优化及ajax编码格式原理解析
2020/03/25 Python
PHP如何对用户密码进行加密
2014/07/31 面试题
护理专科毕业自荐信范文
2014/04/21 职场文书
公司副总经理岗位职责
2015/04/08 职场文书
2015社区六五普法工作总结
2015/04/21 职场文书
离婚答辩状怎么写
2015/05/22 职场文书
小学秋季运动会通讯稿
2015/11/25 职场文书
关于党风廉政建设宣传教育月的活动总结!
2019/08/08 职场文书
Redis遍历所有key的两个命令(KEYS 和 SCAN)
2021/04/12 Redis
解决使用了nginx获取IP地址都是127.0.0.1 的问题
2021/09/25 Servers