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);
原文地址:https://www.cnblogs.com/web-fengmin/p/6396766.html