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 相关文章推荐
使用upstart把nodejs应用封装为系统服务实例
Jun 01 NodeJs
初始Nodejs
Nov 08 NodeJs
Nodejs为什么选择javascript为载体语言
Jan 13 NodeJs
深入浅析NodeJs并发异步的回调处理
Dec 21 NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 NodeJs
Nodejs读取文件时相对路径的正确写法(使用fs模块)
Apr 27 NodeJs
nodejs 子进程正确的打开方式
Jul 03 NodeJs
原生nodejs使用websocket代码分享
Apr 07 NodeJs
nodejs使用node-xlsx生成excel的方法示例
Aug 22 NodeJs
nodejs如何在package.json中设置多条启动命令
Mar 16 NodeJs
浅谈vue websocket nodeJS 进行实时通信踩到的坑
Sep 22 NodeJs
nodeJs项目在阿里云的简单部署
Nov 27 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
re0第二季蕾姆被制作组打入冷宫!艾米莉亚女主扶正,原因唏嘘
2020/04/02 日漫
php对数组排序代码分享
2014/02/24 PHP
PHP提示Cannot modify header information - headers already sent by解决方法
2014/09/22 PHP
php版阿里云OSS图片上传类详解
2016/12/01 PHP
再谈Yii Framework框架中的事件event原理与应用
2020/04/07 PHP
event对象获取方法总结在google浏览器下测试
2013/11/03 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
javascript排序函数实现数字排序
2015/06/26 Javascript
JS+CSS实现鼠标滑过时动态翻滚的导航条效果
2015/09/24 Javascript
13个PHP函数超实用
2015/10/21 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
详解jQuery的表单验证插件--Validation
2016/12/21 Javascript
js图片轮播手动切换特效
2017/01/12 Javascript
微信小程序 使用canvas制作K线实例详解
2017/01/12 Javascript
JavaScript中递归实现的方法及其区别
2017/09/12 Javascript
JS扩展String.prototype.format字符串拼接的功能
2018/03/09 Javascript
angularJs中$http获取后台数据的实例讲解
2018/08/08 Javascript
nodejs开发一个最简单的web服务器实例讲解
2020/01/02 NodeJs
vue使用exif获取图片旋转,压缩的示例代码
2020/12/11 Vue.js
[02:20]2014DOTA2西雅图邀请赛 MVP外卡赛首胜采访
2014/07/09 DOTA
[02:10]三分钟回顾完美世界城市挑战赛
2019/01/24 DOTA
python中pass语句用法实例分析
2015/04/30 Python
Python对列表中的各项进行关联详解
2017/08/15 Python
django如何连接已存在数据的数据库
2018/08/14 Python
Python多线程原理与用法实例剖析
2019/01/22 Python
详解有关PyCharm安装库失败的问题的解决方法
2020/02/02 Python
Python Opencv中用compareHist函数进行直方图比较对比图片
2020/04/07 Python
HTML5 Canvas玩转酷炫大波浪进度图效果实例(附demo)
2016/12/14 HTML / CSS
html5实现输入框fixed定位在屏幕最底部兼容性
2020/07/03 HTML / CSS
世界上最好的精品店:Shoptiques
2018/02/05 全球购物
易程科技软件测试笔试
2013/03/24 面试题
应届中专生自荐书范文
2014/02/13 职场文书
化学教学随笔感言
2014/02/19 职场文书
大学生简历自我评价2015
2015/03/03 职场文书
假如给我三天光明:舟逆水而行,人遇挫而达 
2019/10/29 职场文书
解析mybatis-plus中的resultMap简单使用
2021/11/23 Java/Android