标签:data 详细 isp OLE 传输 通讯 不同的 产生 text
net.connect()实际上是net.createConnection()的别名,还有一个基于net模块子类的new net.socket()构造方法也具备相同的功能,都是用来创建一个新的客户端连接对象。
net.createServer()同样有一个基于net模块子类的new net.server()构造方法与其功能相同,都是用来创建一个新的服务器端网络连接的对象。
net.server事件:
net.server属性:
net.server方法:
err
和 count
。net.socket事件:
connect()
后立即触发。net.socket方法:
net.socket属性:
true
,因为尚未调用 .connect()
或者因为它仍处于连接过程中。用来判断连接是否连接成功。net模块API测试代码一:(基本应用)
1 //server.js 2 let net = require("net"); 3 // var server = net.createServer(); 4 let server = new net.Server(); //创建一个net服务对象 5 server.listen(12306, "127.0.0.1"); //serever.listen()启动net服务监听 6 server.on("listening", function() { //listening事件,启动net服务监听时触发 7 console.log("服务已启动"); 8 }); 9 server.on("connection", function(sockte){ //connection事件,当服务器被客户端成功连接时触发,并且会将连接到的(sockte)客户端对象传入事件回调函数 10 server.unref(); 11 // server.ref(); 12 let address = server.address(); 13 //server.address()返回当前连接服务的客户端地址信息(返回值为一个对象,address:IP地址;familey:协议族;port:端口号) 14 console.log("有新的连接,当前连接服务器客户端:\n" + 15 "IP地址:" + address.address + 16 "; \n协议族:" + address.family + 17 "; \n端口:" + address.port +";"); 18 19 server.getConnections(function(err,conten){ //获取当前并发连接数,也就是用来查看当前这个服务端口被多少个客户端连接 20 try{ 21 console.log(conten); 22 }catch (e) { 23 console.log(err); 24 } 25 }); 26 sockte.on("data",function (data) { //data事件,用来接收消息,并且会将接收到的消息数据data传入回调函数 27 console.log("client:" + data.toString()); 28 sockte.write("hello,client,我已经收到了你的消息了。"); //向服务发送会话,详细sockte参考方法解析 29 }); 30 sockte.on("end",function () { //当连接的另一端调用了sockte.end()方法后会向服务端发送一个FIN包,表示客户端正在关闭连接 31 console.log("接收到FIN,客户端请求关闭了连接。"); 32 }); 33 sockte.on("close",function () { //当客户端的sockte.end()方法触发关闭后,服务端的close事件也能监听到并触发回调函数。 34 console.log("客户端已关闭。"); 35 }); 36 }); 37 //client.js 38 var net = require("net"); 39 var socket = net.connect(12306, "127.0.0.1");//启动客户端网络连接请求 40 socket.on("connect",function(){ 41 console.log("连接的服务地址:"+ socket.remoteAddress); 42 console.log("连接的服务协议族:" + socket.remoteFamily); 43 console.log("连接的服务端口:" + socket.remotePort); 44 console.log("本地的IP地址:" + socket.localAddress); 45 console.log("本地的端口:" + socket.localPort); 46 }); 47 socket.write("hello,server")//向服务发送会话,详细sockte参考方法解析 48 socket.on("data",function (data) {//data事件,用来接收消息,并且会将接收到的消息数据data传入回调函数 49 console.log("server:" + data.toString()); 50 socket.end();//关闭连接 51 }); 52 socket.on("end",function () { 53 console.log("客户端调用了end方法,已经向服务端发送了FIN报文"); 54 }) 55 socket.on("close",function () { //当socket.end()触发连接关闭后,触发close事件 56 console.log("连接以关闭"); 57 });
net模块API测试代码二:(测试:server.unref()、server.ref()、socket.unref()、socket.ref())
1 //server.js 2 let net = require("net"); 3 let server1 = net.createServer(); 4 let server2 = new net.Server(); 5 6 server1.listen(12306, "127.0.0.1"); //serever.listen()启动net服务监听 7 // server2.listen(12307, "127.0.0.1"); //serever.listen()启动net服务监听 8 9 server1.on("listening",function () { 10 console.log("服务server1已启动"); 11 }); 12 // server2.on("listening",function () { 13 // console.log("服务server2已启动"); 14 // }); 15 16 server1.on("connection",function (socket) { 17 server1.unref(); 18 server1.ref(); 19 server1.unref();//这个无效了 20 console.log("服务server1有新的连接。"); 21 socket.on("data",function (data) { 22 console.log("client1:" + data.toString()); 23 socket.write("hello,client1,我已经收到你的消息了"); 24 }); 25 socket.on("end",function () { //当连接的另一端调用了sockte.end()方法后会向服务端发送一个FIN包,表示客户端正在关闭连接 26 console.log("接收到FIN,客户端请求关闭了连接。"); 27 }); 28 socket.on("close",function () { //当客户端的sockte.end()方法触发关闭后,服务端的close事件也能监听到并触发回调函数。 29 console.log("客户端已关闭。"); 30 }); 31 }); 32 // server2.on("connection",function (socket) { 33 // console.log("服务server2有新的连接。"); 34 // }); 35 36 //client.js 37 var net = require("net"); 38 var socket1 = net.connect(12306, "127.0.0.1");//启动客户端网络连接请求 39 // var socket2 = net.connect(12307, "127.0.0.1"); 40 41 socket1.write("hello,server1"); 42 // socket2.write("hello,server2"); 43 // 44 socket1.on("data",function (data) { 45 console.log("server1:" + data.toString()); 46 // socket1.end(); 47 socket1.unref(); 48 }); 49 socket1.on("end",function () { 50 console.log("客户端调用了end方法,已经向服务端发送了FIN报文"); 51 }) 52 socket1.on("close",function () { //当socket.end()触发连接关闭后,触发close事件 53 console.log("连接以关闭"); 54 });
net模块API测试代码三:(测试socket.end()、socket.destroy()、socket.destroyed)
1 //server.js 2 let net = require("net"); 3 let server = net.createServer(); 4 server.listen(12306, "127.0.0.1"); 5 server.on("listening",function () { 6 console.log("服务已启动"); 7 }); 8 server.on("connection",function (socket) { 9 socket.on("data",function(data){ 10 try{ 11 console.log("client:" + data.toString()); 12 throw new Error("测试server的Error事件"); 13 }catch (e) { 14 console.log("错误处理后关闭客户端的连接"); 15 console.log(socket.destroyed);//false 16 socket.destroy();//这里可以关闭客户端的连接,但不会关闭server服务。相比end,destroy会清除该socket上的所有io操作。 17 console.log(socket.destroyed);//true 18 // socket.end();//end也可以关闭客户端连接,且不会关闭server服务。 19 //try、catch处理错误,但不会关闭客户端连接,在服务端使用 20 // console.log(socket.) 21 } 22 }); 23 }); 24 //client.js 25 let net = require("net"); 26 let socket = net.connect(12306, "127.0.0.1"); 27 socket.on("connect",function () { 28 socket.write("hello,server!"); 29 }); 30 socket.on("end",function () { 31 console.log("end与destroy方法调用都会触发这个方法。"); 32 }) 33 socket.on("close",function () { 34 console.log("连接以关闭"); 35 })
net模块API测试代码四:(测试setTimeout()、timeout事件)
1 //server.js 2 let net = require("net"); 3 let server = net.createServer(); 4 server.listen(12306, "127.0.0.1"); 5 server.on("listening",function () { 6 console.log("服务已启动"); 7 }); 8 server.on("connection",function (socket) { 9 socket.on("data",function(data){ 10 console.log("client:" + data.toString()); 11 }); 12 }); 13 14 //client.js 15 let net = require("net"); 16 let socket = net.connect(12306, "127.0.0.1"); 17 socket.on("connect",function () { 18 socket.write("hello,server!");//向服务器发送消息 19 socket.setTimeout(5000,function () { 20 console.log("我在什么时候调用呢?") 21 });//发送消息后启动超时监听事件,如果在指定的事件内没有收到服务端的消息,就会触发回调函数及超时事件。(这里没有使用超时回调函数) 22 }); 23 socket.on("timeout",function () { 24 console.log("连接超时,执行end关闭连接"); 25 socket.end();//socket 将会收到一个 ‘timeout‘ 事件,但连接不会被断开。用户必须手动调用 socket.end() 或 socket.destroy() 来断开连接。 26 }) 27 socket.on("end",function () { 28 console.log("end与destroy方法调用都会触发这个方法。"); 29 }) 30 socket.on("close",function () { 31 console.log("连接以关闭"); 32 })
前面只针对net的API做了解析,并未就net的实现基础做任何阐述,net作为nodejs中重要的网络应用底层模块实际是基于TCP/IP协议的API。所以如果net.server如果接收到一个http请求的话,他会解析出一个http报文。这是因为net模块底层只负责解析TCP/IP协议的套字节,并不解析http的套字节,比如启动下面这个服务程序,然后通过浏览器访问这个服务,服务接收到请求后会打印出一个完整的http请求报文头:
1 let net = require("net"); 2 let server = net.createServer(); 3 server.listen(12306, "127.0.0.1"); 4 server.on("listening",function () { 5 console.log("服务已启动"); 6 }); 7 server.on("connection",function (socket) { 8 socket.on("data",function(data){ 9 console.log(data.toString()); 10 }); 11 });
在浏览器通过http协议发起请求:
http://127.0.0.1:12306
然后控制台会打印出一个完整的http请求报文:
net启动的网络服务能解析出http报文,也就意味着可以通过net服务向浏览器响应一个http报文,并且可以被浏览器解析:
1 let net = require("net"); 2 let server = net.createServer(); 3 server.listen(12306, "127.0.0.1"); 4 server.on("listening",function () { 5 console.log("服务已启动"); 6 }); 7 server.on("connection",function (socket) { 8 socket.on("data",function(data){ 9 console.log(data.toString()); 10 //手写一个http响应报文,报文内容为一个html页面 11 socket.write("HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\n<html><h1>hello, browser!</h1></html>") 12 }); 13 });
通过浏览器可以通过请求http://127.0.0.1:12306可以获得响应,服务还可以获得完整的http报文也就意味着可以手动解析报文,来分析http请求的内容是什么,沿着这样的思路就可以通过解析http请求来给浏览器响应对应的请求资源,用下面这个请求index.html包含一个图片的页面作为示例:
//服务端文件 index.html server.js image.jpg
html代码:
<h1>
hello,browser!
</h1>
<img src="./image.jpg"/>
server.js
1 let net = require("net"); 2 let fs = require("fs"); 3 4 let server = net.createServer(); 5 server.listen(12306, "127.0.0.1"); 6 server.on("listening",function () { 7 console.log("服务已启动"); 8 }); 9 10 server.on("connection",function (socket) { 11 try{ 12 socket.on("data",function(data){ 13 let request = data.toString().split("\r\n"); 14 let url = request[0].split(" ")[1]; 15 let fileData = fs.readFileSync(__dirname + url); 16 //手写一个http响应报文,报文内容为一个html页面 17 // let writeState = socket.write("HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\n<html><h1>hello, browser!</h1></html>"); 18 // let writeState = socket.write("HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\n" + fileData.toString()); 19 //当需要发送文件时,特别是html文件,其内部会包含很多其他文件的引用,如果采用拼接到报文头部后面无法被socket正常解析内部文件引用 20 //可是依靠TCP协议传输特性,每次先将独立的HTTP头部发送出去,然后再通过socket.write发送文件,当socket.write发送文件时会自动解析文件内容 21 socket.write("HTTP1.1 200OK\r\nContent-Type: text/html\r\n\r\n"); 22 let writeState = socket.write(fileData); 23 if(writeState){ 24 socket.end();//当成功发送数据以后关闭连接 25 }else{ 26 socket.write("HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\n<html><h1>404</h1></html>"); 27 socket.end(); 28 } 29 }); 30 }catch(e){ 31 socket.destroy(e);//强制关闭socket所有io操作,并将传入的e:Error对象传递给socket的Error监听事件 32 } 33 socket.on("error",function (e) { 34 console.log(e); 35 }) 36 });
通常情况下我们不会把前端代码与后端代码放到一起,特别在开发的时候,为了更方便前端代码连接服务测试,这时候我们可以在服务端配置前端代码的路径以及测试端口:
//假设将前端文件放到桌面 web //根目录 html //html文件 index.html css //css文件 js //js文件 image //图片文件 image.jpg json //json文件
1 <!DOCTYPE html> 2 <head> 3 <title>Node-Net-Fs-Server</title> 4 <link rel="stylesheet" href=""> 5 </head> 6 <body> 7 <h3>hello,browser!</h3> 8 <img src="./image/image.jpg"/> 9 </body> 10 </html>
服务端:
server.config
server.js
serverConfig.js
可以通过server.config配置不同的端口与前端文件路径:
port=12306
path= 桌面的路径 + \web
1 //serverConfig.js 用来解析配置文件 2 let fs = require("fs"); 3 4 function analysisConfig(configFile){ 5 let obj = {}; 6 let arr = configFile.toString().split("\r\n"); 7 for(let i = 0; i < arr.length; i++){ 8 let item = arr[i].split("="); 9 obj[item[0]] = item[1]; 10 } 11 return obj; 12 } 13 // 文件模型, 文件数据对象 14 let configFile, configData; 15 try{ 16 configFile = fs.readFileSync(__dirname + "/server.config"); 17 configData = analysisConfig(configFile); 18 }catch (e) { 19 console.log("解析server.config文件出错!",e); 20 } 21 22 module.exports = configData;
1 //srever.js 2 let net = require("net"); 3 let fs = require("fs"); 4 let config = require("./serverConfig.js"); 5 let server = net.createServer(); 6 server.listen(parseInt(config["port"]),"127.0.0.1"); 7 server.on("listening",function () { 8 console.log("服务已启动"); 9 }); 10 server.on("connection",function (socket) { 11 socket.on("data",function (data) { 12 try{ 13 let request = data.toString().split("\r\n"); 14 let url = request[0].split(" ")[1]; 15 let urlType = url.split("/")[1]; 16 if(url === "/" || url === "/index.html"){//这里响应首页 17 socket.write("HTTP1.1 200OK\r\nContent-Type: text/html\r\n\r\n"); 18 socket.write(fs.readFileSync(config["HTMLPath"] + "/index.html")); 19 }else if(urlType === ‘image‘ || urlType === ‘html‘ || urlType === ‘css‘ || urlType === ‘js‘ || urlType===‘json‘){ 20 //这里主要用来响应html、css、js内部的引用文件 21 socket.write("HTTP1.1 200OK\r\nContent-Type: text/html\r\n\r\n"); 22 socket.write(fs.readFileSync(config["path"] + url)); 23 }else{ //如果有请求除html、css、js、image以外的其他文件就在服务器相对路径下查找 24 socket.write("HTTP1.1 200OK\r\nContent-Type: text/html\r\n\r\n"); 25 socket.write(fs.readFileSync(__dirname + url)); 26 } 27 socket.end(); 28 }catch(e){//如果出现请求不存在的数据fs在解析文件时会抛出错误,这里返回404页面,然后关闭当前会话。 29 //这里你可能会想到如果请求页面内部引用文件不存在呢? 30 //这种情况可以在响应页面内部文件之前先判断,如果文件存在再读写文件,然而这种情况HTTP模块已经提供了非常完善的机制。 31 socket.write("HTTP1.1 200OK\r\nContent-Type: text/html\r\n\r\n<html><h1>404!</h1></html>"); 32 socket.destroy(e); 33 } 34 }); 35 socket.on("error",function (e) { 36 console.log(e); 37 }) 38 });
标签:data 详细 isp OLE 传输 通讯 不同的 产生 text
原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11915019.html