当前位置: 首页 > 后端技术 > Node.js

节点网络通讯

时间:2023-04-04 00:33:32 Node.js

网络通信一、网络通信一、网络通信的基本原理通信的必要条件:主机之间必须有传输介质(传输数据信号)主机上必须有网卡设备(数据信号的调制解调)主机间网络协商速度图:2.网络通信方式交换机通信路由器通信图:(使用Mac地址定位主机)缺点:交换机的接口数量有上限数量较多局域网内的主机,会引起广播风暴(任何报文都需要其他机器接收,然后确认接受是否有效)路由器使用示意图(连接局域网):3.网络层模型OSI七层模型:数据封装与解封装(TCP/IP五层协议模式):参考:https://blog.csdn.net/weixin_...4.tcp协议tcp消息结构图:公共控制域:三次握手图:四次挥手图:为什么挥手中间的两次不能合并?服务器将服务于多个客户端。服务器收到报文后,可能无法及时将结果返回给TCP协议。总结:TCP处于传输层,基于端口,面向连接。首先需要建立主机之间的通信。双向数据通道TCP握手和挥手本质上是四次2.创建TCP通信Net模块,实现底层通信接口的通信过程:创建服务器:接收和写回客户端数据创建客户端:发送和接收服务器数据数据传输:内置服务事件和读写数据核心的方法内置通信事件:监听事件:调用server后触发连接事件.listen方法:建立新连接时触发关闭事件:触发错误事件服务器关闭时:发生错误时触发通信事件&方法:数据事件:接收到数据时触发此事件写方法:在套接字上发送数据,默认为UTF8编码结束操作:当一个结束时触发socket发送一个FIN包,endreadableend1.net模块在节点中使用tcp连接的创建和通信:server:constnet=require('net');//创建一个服务器实例constserver=net.创建服务器();常量端口=1234;constHOST='localhost';//监听端口server.listen(PORT,HOST);server.on('listening',()=>{console.log(`服务器已在${HOST}开启:${PORT}`);});//只接收消息并写回消息Socket双工流server.on('connection',(socket)=>{console.log('有客户端连接');socket.on('data',(chunk)=>{constmsg=chunk.toString();console.log('client:'+msg);//写回消息socket.write(Buffer.from('helloclient'));})});server.on('close',()=>{console.log('服务器关闭');})server.on('error',(err)=>{console.log('服务器发生错误',err);})客户端:constnet=require('net');constclient=net.createConnection({port:1234,host:'127.0.0.1'})client.on('connect',()=>{client.write('你好服务器');})client.on('data',(chunk)=>{console.log('server:'+chunk.toString());});client.on('err',()=>{console.log('客户端有错误');});client.on('close',()=>{console.log('客户端已关闭');})2.TCP粘包问题显示:客户端代码:client.on('connect',()=>{client.write('helloserver');client.write('helloserver');client.write('helloserver');client.write('helloserver');})服务器代码:server.on('connection',(socket)=>{console.log('有客户端连接');socket.on('data',(chunk)=>{constmsg=chunk.toString();console.log('client:'+msg);//写回消息socket.write(Buffer.from('你好客户'));})});结果显示:'client:'打印了一次,出现了粘包问题。1.客户端断断续续发送数据代码:letdataArr=['helloserver','helloserver-2','helloserver-3','helloserver-4',]client.on('connect',()=>{for(leti=0;i{client.write(val)},1000*(index+1))})(dataArr[i],i)}})正确效果:2.数据封装和拆包协议数据包结构:数据传输过程:数据编码,得到二进制数据包将数据按规则拆解,得到指定的数据长度Buffer数据读写:writeInt16BE:从指定位置写入值readInt16BE:从指定位置开始读取数据包和解包类Implementation:classMyTransformCode{constructor(){this.packageHeaderLen=4;这个.serialNum=0;这个.serialLen=2;}//编码encode(data,serialNum){letbody=Buffer.from(data);//先按01按照指定长度申请bufferconstheaderBuf=Buffer.alloc(this.packageHeaderLen);//02然后将数据写入缓冲区headerBuf.writeInt16BE(serialNum||this.serialNum);headerBuf.writeInt16BE(body.length,this.serialLen);if(serialNum===undefined){this.serialNum++;}returnBuffer.concat([headerBuf,body]);}decode(buffer){letheaderBuf=buffer.slice(0,this.packageHeaderLen);constbodyBuf=buffer.slice(this.packageHeaderLen);return{serialNum:headerBuf.readInt16BE(),bodyLength:headerBuf.readInt16BE(this.serialLen),body:bodyBuf.toString()}}//获取包长度getPackageLen(buffer){if(buffer.length{console.log('有客户端连接');socket.on('data',(chunk)=>{if(overageBuffer){chunk=Buffer.concat([overageBuffer,chunk]);overageBuffer=null;}让packageLen=0;而(packageLen=ts.getPackageLen(chunk)){constpackageCon=chunk.slice(0,packageLen);chunk=chunk.slice(packageLen);constret=ts.decode(packageCon);console.log(ret);//写回消息socket.write(ts.encode(ret.body,ret.serialNum));}overageBuffer=chunk;})});//clientclient.on('connect',()=>{client.write(ts.encode('拉钩教育'));client.write(ts.encode('拉钩教育'));client.write(ts.encode('拉勾教育'));client.write(ts.encode('拉勾教育'));client.write(ts.encode('拉钩教育'));client.write(ts.encode('拉钩教育'));})client.on('data',(chunk)=>{if(overageBuffer){chunk=Buffer.concat([overageBuffer,chunk]);overageBuffer=null;}letpackageLen=0;while(packageLen=ts.getPackageLen(chunk)){constpackageCon=chunk.slice(0,packageLen);chunk=chunk.slice(packageLen);constret=ts.decode(packageCon);console.log(ret);}overageBuffer=chunk;});三、http协议1、使用http模块开启一个http服务器:consthttp=require('http');letserver=http.createServer((req,res)=>{res.end('helloworld');});server.listen(1234,()=>{console.log('serverislistening1234');})获取http请求信息:consthttp=require('http');consturl=require('url');constserver=http.createServer((req,res)=>{//请求路径let{pathname,query}=url.parse(req.url,true);console.log('pahtinfo:',pathname,'----',query)//请求方法console.log('method:',req.method);//版本号console.log('httpVersion:',req.httpVersion);//请求头console.log('headers:',req.headers);letarr=[]//请求体req.on('data',(data)=>{arr.push(data);});req.on('end',()=>{console.log('body:',Buffer.concat(arr).toString())})res.end('helloclient')});server.listen(1234,()=>{console.log('serverislistening1234');})设置http响应:consthttp=require('http');constserver=http.createServer((req,res)=>{console.log('requestenter');//设置响应状态码res.statusCode=302;//设置响应头信息res.setHeader('Content-Type','text/html;charset=utf-8');//res.write('ok');res.end('江江');});server.listen(1234,()=>{console.log('servetislistening1234');})2.客户端代理agent-server代码:consthttp=require('http');consturl=require('url');constqeurystring=require('querystring');constserver=http.createServer((req,res)=>{let{pathname,query}=url.parse(req.网址,真实);console.log(路径名,'---',查询);让arr=[];req.on('data',(data)=>{arr.push(data);})req.on('end',()=>{letobj=Buffer.concat(arr).toString();if(req.headers['content-type']=='application/json'){让ret=JSON.parse(obj);ret.add='add';res.end(JSON.stringify(ret));}elseif(req.headers['content-type']=='application/x-www-form-urlencoded'){让ret=qeurystring.parse(obj);res.end(JSON.stringify(ret));}})})server.listen(1234,()=>{console.log('serverislistening1234');})agent-client代码:consthttp=require('http');letoptions={host:'localhost',port:1234,path:'/',method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded',}}letreq=http.request(options,(res)=>{letarr=[];res.on('data',(chunk)=>{arr.push(ch未知);})res.on('end',()=>{console.log(Buffer.concat(arr).toString());})})//req.end(`{"name":"zhangsan"}`)req.end(`a=1&b=2`)3.代理客户端跨域外部服务器代码:consthttp=require('http');constserver=http.createServer((req,res)=>{letarr=[];req.on('data',(data)=>{arr.push(data);})req.on('end',()=>{console.log(Buffer.concat(arr).toString());res.end('外部服务器端数据');})})server.listen(1234,()=>{console.log('externalserverstart');})代理客户端服务器:consthttp=require('http');letoptions={host:'localhost',port:1234,path:'/',method:'POST'}letserver=http.createServer((request,response)=>{letreq=http.request(options,(res)=>{letarr=[];res.on('data',(data)=>{arr.push(data);})res.on('end',()=>{letret=Buffer.concat(arr).toString();response.setHeader('Content-Type','text/html;charset=utf-8');console.log('ret',ret)response.end(ret)})})req.end('helloworld');})server.listen(2345,()=>{console.log('本地服务器已启动');})