zoukankan      html  css  js  c++  java
  • TCP与UDP

    TCP

    ·TCP(Transmission Control Protocol传输控制协议)是一个可靠的面向连接的传输层协议

      TCP/IP分层模型分为了七层,在每一层中都包含了一些相对独立的具体的协议。从上往下分为应用层、表示层、会话层、传输层、网络层,数据链路层和物理层。

     

      tcp数据包控制位URG、ACK、PSH、PST、SYN、FIN,对tcp的连接、传输和断开进行指挥。

     

    ·它可以让你将数据从一台计算机完整有序的传输到另一台计算机,内置机制能够控制数据包的延迟率及丢包率不会太高

    ·发送方将数据转为字节流分成,将数据交给IP层。接收方接收后重新装配成原始的数据。

      应用层发出请求(数据,有含义的,http等),发出的请求在传输层添加TCP控制信息(TCP头部+数据=>数据段segment),再传递给网络层添加IP头部标识唯一地址(IP头部+数据段=>数据包Packet),然后到达数据链路层添加MAC头部及尾部让两者的网卡进行通信,之后通过物理层(网线、光纤等)以比特流的形式进行传输。到达目标主机之后,由下向上进行解析,在数据链路层去除mac头尾,再向上到达网络层去掉IP头部,再向上到达传输层去除TCP头部,最终到达应用层得到数据。

    ·TCP对字符和字符编码是完全无知的,不同的编码会导致传输的字节数不同

    ·TCP使用流控制来确保两点之间传输数据的平衡,以防止快速的发送方淹没慢速的接收方

    ·TCP在传输前要经过3次握手才能形成会话,只有会话形成后,服务器端和客户端才能互相发送数据。

      TCP三次握手:第一次握手是主机A向主机B请求建立连接,发送SYN;第二次握手是主机B同意主机A的连接请求,发送SYN、ACK;第三次握手是主机A向主机B发送ACK。

    ·在会话过程中,服务器和客户端分别提供一个套接字(socket),这两个套接字共同形成一个连接。服务器和客户端通过套接字进行通信

    TCP服务器

    开发过程中主要控制的是应用层和传输层。

    net模块用于实现TCP服务器端和客户端之间的通信。

        ·options参数:

        -allowHalfOpen:是否允许半开连接。属性值为false时,TCP服务器收到客户端的FIN包时会回发FIN包,为true时,服务器收到客户端FIN包不回发FIN包

        ·connectionListener=function(socket){}客户端连接时的回调函数

        -socket表示服务器监听的socket端口对象

      ·返回被创建的服务器server

      ·listen(port,[host],[backlog],[callback])  

        -port监听的端口号

        -host监听的IP地址或主机名

        -backlog等待队列中的最大数量(默认511)

    创建一个tcpserver.js

    var net = require('net');
    var util = require('util');
    
    //net.Socket 双工流 Duplux
    var server = net.createServer({allowHalfOpen:true},function(socket){
      console.log(util.inspect(socket.address()));
      //查看当前连接数量
      server.getConnections(function(err,count){
          console.log(count);
      });
        socket.on('error',function(err){//监听客户端的错误
            console.log(err);
            socket.destroy();
        });
      socket.setEncoding('utf8');//可读流的方法
       socket.on('data',function(data){
        console.log(data);
       })
        socket.on('close',function(err){//end事件与close事件的区别是:close一定会触发,end则不一定触发
            console.log(err);
            socket.destroy();
        })
    })
    server.on('error',function(err){//监听服务器端的错误
      console.log(err);
    });
    server.listen(8089,function(){
      console.log(util.inspect(server.address()));
        setTimeout(function(){
            server.close();//客户端全都断开后才会关闭服务端
        },3000)
    });
    server.on('close',function(err){
        console.log('服务器端正常关闭');
    });

    写一个tcpSocket.js

    var net = require('net');
    var util = require('util');
    var fs = require('fs');
    //net.Socket 双工流 Duplux
    var ws = fs.createWriteStream('./socket.txt');
    var server = net.createServer({allowHalfOpen:true},function(socket){
      socket.setTimeout(10*1000);
      socket.on('timeout',function(){
        socket.resume();
        socket.pipe(ws,{end:false});
        ws.write(socket.remoteAddress)
      });
    
    })
    server.on('error',function(err){
      console.log(err);
    });
    server.listen(8089,function(){
      console.log(util.inspect(server.address()));
    });

     socket

      ·net.socket代表一个socket端口对象

      ·socket端口对象可用来读取客户端发送的流数据,读到数据时触发data事件

        -socket.on('data',function(){})

      ·创建socket: var socket = new net.Socket([options])

        -options

          -fd socket文件描述符

          -type 客户端协议,tcp4或tcp6

          -allowHalfOpen是否允许半开连接

      .连接TCP服务器:socket.connect(port,[host],[connectListener])

        -port 端口

        -host主机地址

        -connectListener 连接成功后的监听

      ·向服务器发送数据:socket.write(data,[encoding],[callback])

        -data 写入的数据

        -encoding 编码

     创建一个tcpClient.js

    var net = require('net');
    var util = require('util');
    var socket = new net.Socket({allowHalfOpen:true});
    socket.setEncoding('utf8');
    
    socket.connect(8089,'localhost',function(){
      socket.write('hello');//客户端向服务端发送数据
      socket.on('data',function(data){//客户端接收来自服务器的方法
        console.log(data);
      });
    });

     net类方法

      ·net.isIP 判断字符串是否是IP

      ·net.isIPv4 是否是IPv4地址

      ·net.isIPv6 是否IPv6地址

    UDP

      tcp是基于连接的协议,进行通信前客户端与服务器要先建立连接。UDP是面向非连接的协议,可能直接发数据包

      UDP不要求分组顺序到达传输层中

      受网络影响可能丢失数据包

      资源消耗少,处理速度快,适合音频、视频和普通数据传输

      UDP协议中的包成为数据报datagram

      UDP协议不区分客户端和服务端的概念,都可以创建socket对象

        ·var socket = dgram.createSocket(type,[callback])

          ·type 协议类型可以是udp4或udp6

          ·callback = function(msg,rinfo)收到数据时的回调函数

            -msg收到的数据

            -rinfo

              -address 发送者的IP

              -family 地址类型

              -port发送者的socket端口号

              -size发送者发送的数据字节数

        ·绑定地址和端口  socket.bind(port,[address],[callback])

        ·发送数据 socket.send(buf,offset,length,port,address,[callback])

          -buf 要发送的数据buffer

          -offset从缓存区中第几个字节开始发送数据

          -length发送数据的字节数

          -port接收数据的端口号

          -address 接收数据的IP地址

          -callback function(err,bytes){}发送完毕时所调的回调函数

            -err 发送出错时触发的错误对象

            -bytes发送数据的字节数

    创建一个udpServer.js

    var dgram = require('dgram');
    var socket = dgram.createSocket('udp4');
    socket.on('message',function(msg,rinfo){
      console.log(msg.toString());
      console.log(rinfo);
       socket.send(msg,0,msg.length,rinfo.port,rinfo.address);
    });
    socket.bind(41234,'localhost');

    创建一个udpClient.js

    var dgram = require('dgram');
    var socket = dgram.createSocket('udp4');
    socket.on('message',function(msg,rinfo){
        console.log(msg.toString());
        console.log(rinfo);
    });
    socket.send(new Buffer('珠峰培训'),0,6,41234,'localhost',function(err,bytes){
        console.log('发送了个%d字节',bytes);
    });
    socket.on('error',function(err){
        console.error(err);
    });

     创建一个即时通讯的tcp聊天chatServer.js

    /**
     * 1.创建一个服务器
     * 2. 客户端可以连接服务器
     * 3.客户端可以发言,然后广播给大家
     * 4.客户端连接和退出后都要通知大家。
     * 5.显示当前的在线人数
     */
    var net = require('net');
    var util = require('util');
    var clients = {};
    var server = net.createServer(function(socket){
     var nickname;
     socket.setEncoding('utf8');
        server.getConnections(function(err,count){
            socket.write('欢迎光临,当前在线'+count+'人,请输入用户名
    >');
        });
    
     socket.on('data',function(data){
       //console.log(new Buffer(data));
       data = data.replace(/
    /,'');
       if(nickname){
           broadcast(nickname,nickname+":"+data+'
    ');
       }else{
           nickname = data;
           clients[nickname] = socket;
           broadcast(nickname,nickname+'加入了聊天室
    ');
       }
     });
     socket.on('end',function(){
         broadcast(nickname,nickname+'离开了聊天室
    ');
         clients[nickname].destroy();
         delete clients[nickname];
     });
        socket.on('error',function(){
    
        });
        socket.on('close',function(){
    
        });
    })
    function broadcast(nickname,msg){
        for(var name in clients){
            if(nickname != name)
                clients[name].write(msg);
        }
    }
    server.listen(8088);
  • 相关阅读:
    国外的零日漏洞记录片(中文字幕)
    浅谈网络爬虫中广度优先算法和代码实现
    浅谈网络爬虫中深度优先算法和简单代码实现
    Python正则表达式的简单应用和示例演示
    Python正则表达式初识(十)附正则表达式总结
    Python正则表达式初识(九)
    Python正则表达式初识(八)
    Python正则表达式初识(七)
    Python正则表达式初识(六)
    Python正则表达式初识(五)
  • 原文地址:https://www.cnblogs.com/web-fengmin/p/6396766.html
Copyright © 2011-2022 走看看