前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >七层协议和TCP/IP协议、三次握手四次挥手、BIO、NIO(Netty前置)

七层协议和TCP/IP协议、三次握手四次挥手、BIO、NIO(Netty前置)

原创
作者头像
花花与Java
修改2020-12-03 18:01:49
5180
修改2020-12-03 18:01:49
举报
文章被收录于专栏:架构架构

一 基础

1.1 概述

1 网络分层中的IOS七层模型、TCP/IP协议族、TCP、IP,这些有什么不同

2 TCP协议通信过程中的三次握手和四次挥手到底是什么流程?

1.2 软件架构

在生活中,我们经常用QQ、微信、百度云盘、Goole、IE浏览器、火狐浏览器......。可以总结为两大类,c/s(客户端/服务端)和b/s(浏览器/服务器)结构。这两种架构是两台计算机通过某中协议来网络中进行通信。

1.3 基本概念(通信协议/ip/端口)

  1. 通信协议 就是定义了在网络中计算机之间进行通信的一种规则。因为电脑是由许许多多加的厂商来做的,如果传出的数据格式不一样、传输数据格式、解析数据的格式不一样,就没法实现所有电脑通信。
  2. ip 在整个网络中,电脑的唯一标识。ip分为IPV4和IPV6,ipv4占用4个字节,ipv6占用16个字节。目前使用较多的还是ipv4。
  3. 端口 在计算机中,进程的唯一标识。端口号是用两个字节表示,取值范围为0-65535,0-1023基本为系统端口,我们写的程序端口号应在1024以上。

二 计算机通信分层

2.1 七成模型、TCP/IP协议族、TCP、IP这些是不是同一个东西?

1 ISO国际标准话组织在研究网络通信,建立了OSI模型(开放系统互联参考模型)。即为标准的7层架构。(理论上分层模型)

2 TCP/IP协议族,最早由美国国防部的ARPA网项目,也被DoD模型。(实践过程中的模型)

3 TCP,IP这是网络分层中具体的协议。

2.2 访问淘宝经历了网络流程

1 我们在浏览器输入淘宝的网址。

2 (本机)浏览器将请求发送,应用层-》传输层-》网络层-》数据链路层

3 (网络传输过程)-》到路由器-》交换机

4 (淘宝服务器)-》到达淘宝服务器-》链路层-》网络层-》传输层-》应用层,获取数据

5 (响应数据)-》然后再原路返回。

三 网络传输层解析

3.1 Socket是什么?

Socket是位于应用层和传输层的一个抽象层。提供了一套接口来调用TCP/IP协议的API。

3.2 Socket通信流程

3.3 网络传输层的TCP协议详解

  1. 概述 TCP是Transmission COntrol Protocol的简称,中文名也叫做传输控制协议。它具有的特性如下。undefineda 数据传输前必须要建立连接,数据传输完,必须释放连接。undefinedb 传输的数据无差错,不丢失,不重复,且顺序和源数据一致。undefinedc 在传输的过程中,数据拆分为不同的段,也就是segment。undefinedd 效率低,因为是面向连接的协议,通信之前必须要建立连接。
  2. TCP首部进行详解
    源端口和目的端口:数据从哪个进程来到哪个进程去。

序号和确认号:TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传输流中,每个字节一个序号。

URG:表示本报文段中发送的数据是否包含紧急数据。URG=1,表示有紧急数据。后面的紧急指针字段

只有当URG=1时才有效。

ACK:表示是否前面的确认号字段是否有效。ACK=1,表示有效。只有当ACK=1时,前面的确认号字段才

有效。TCP规定,连接建立后,ACK必须为1。

PSH:告诉对方收到该报文段后是否应该立即把数据推送给上层。如果为1,则表示对方应当立即把数据

提交给上层,而不是缓存起来。

RST:只有当RST=1时才有用。如果你收到一个RST=1的报文,说明你与主机的连接出现了严重错误(如

主机崩溃),必须释放连接,然后再重新建立连接。或者说明你上次发送给主机的数据有问题,主机拒绝

响应。

SYN:在建立连接时使用,用来同步序号。当SYN=1,ACK=0时,表示这是一个请求建立连接的报文段;

当SYN=1,ACK=1时,表示对方同意建立连接。SYN=1,说明这是一个请求建立连接或同意建立连接的

报文。只有在前两次握手中SYN才置为1。

FIN:标记数据是否发送完毕。如果FIN=1,就相当于告诉对方:“我的数据已经发送完毕,你可以释放

连接了。

窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而

达到流量控制。

选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接

方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本

端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中

加入额外的零,以保证TCP头是32的整数倍

数据部分: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段

仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时

的许多情况中,也会发送不带任何数据的报文段。

四 TCP断开和连接的原理刨析(三次握手和四次挥手)

4.1 数据在传递过程中,字段解释

SYN(synchronous建立连接) 请求建立连接,并在其序列号字段进行序列号的初始值设定。建立连接,设置为1。

ACK(acknowledgement 确认) 确认号是否有效,一般置为1

PSH(push传送) 提示接受端应用程序立即从TCP缓冲区把数据读走。

FIN(finish结束) 希望断开连接。

RST(reset重置) 对方要求重新建立连接,复位。

URG(urgent紧急) 紧急指针是否有效。为2,表示某一位被优先处理。

4.2 BIO

4.2.1 BIO代码实现

代码语言:txt
复制
//服务端代码
public class ServerSocket {
    public static void main(String[] args) throws Exception {
        //创建ServerSocket对象,用于客户端的连接
        java.net.ServerSocket serverSocket = new java.net.ServerSocket(8989);
        //定义输入流对象读取数据
        byte[] bytes = new byte[1024];
        try {

            while (true) {
                System.out.println("服务端发生阻塞,等待连接....");
                //调用accept方法监听客户端,阻塞方法
                Socket accept = serverSocket.accept();
                //调用Socket对象的方法获取输入流对象
                InputStream inputStream = ((Socket) accept).getInputStream();
                System.out.println("服务端发生阻塞,等待接收数据....");
                int read = inputStream.read(bytes);
                System.out.println(new String(bytes, 0, read));
                //关闭资源
                accept.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
        }
    }
}

//客户端代码
public class ClientSocket {
    public static void main(String[] args) throws  Exception {
        //创建Socket对象,与服务端Socket建立连接
        Socket socket=new Socket("127.0.0.1",8989);
        //获取输出流对象
        OutputStream  outputStream=socket.getOutputStream();
        System.out.println("客户端阻塞,接收键盘输入....");
        //接收键盘输入,模拟延迟消息发送
        Scanner scanner=new Scanner(System.in);
        String  scannerString=scanner.next();
        outputStream.write(scannerString.getBytes());
        System.out.println("客户端录入完成....");
	     //使用输出流对象写入数据
//        outputStream.write("itheima-TCP".getBytes());
         //释放资源
        socket.close();

    }
}

4.2.2 BIO中API讲解

  1. Socket a 构造方法Socket():无参构造方法。 Socket(InetAddress address,int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口。 Socket(InetAddress address,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。 Socket(String host,int port):创建一个流套接字并将其连接到指定主机上的指定端口。 Socket(String host,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。Socket 会通过调用 bind() 函数来绑定提供的本地地址及端口。b 普通方法void bind(SocketAddress bindpoint):将套接字绑定到本地地址。 void close():关闭此套接字。 void connect(SocketAddress endpoint):将此套接字连接到服务器。 InetAddress getInetAddress():返回套接字的连接地址。 InetAddress getLocalAddress():获取套接字绑定的本地地址。 InputStream getInputStream():返回此套接字的输入流。 OutputStream getOutputStream():返回此套接字的输出流。 SocketAddress getLocalSocketAddress():返回此套接字绑定的端点地址,如果尚未绑定则返回null。 SocketAddress getRemoteSocketAddress():返回此套接字的连接的端点地址,如果尚未连接则返回 null。 int getLoacalPort():返回此套接字绑定的本地端口。 intgetPort():返回此套接字连接的远程端口ServerSocket():无参构造方法。 ServerSocket(int port):创建绑定到特定端口的服务器套接字。 ServerSocket(int port,int backlog):使用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口。 ServerSocket(int port,int backlog,InetAddress bindAddr):使用指定的端口、监听 backlog 和要绑定到本地的 IP 地址创建服务器b 普通方法Server accept():监听并接收到此套接字的连接。 void bind(SocketAddress endpoint):将 ServerSocket 绑定到指定地址(IP 地址和端口号)。 void close():关闭此套接字。 InetAddress getInetAddress():返回此服务器套接字的本地地址。 int getLocalPort():返回此套接字监听的端口。 SocketAddress getLocalSoclcetAddress():返回此套接字绑定的端口的地址,如果尚未绑定则返回 null。 int getReceiveBufferSize():获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是从ServerSocket 接收的套接字的建议缓冲区大小。 accept()方法会返回一个和客户端Socket对象相连的Socket对象。使用Socket的getOutputStream可以向客户端发送信息。使getIutputStreamke可以获取客户端传过来数据。4.3 TCP协议中,建立连接三次握手
  2. WebSocket a 构造方法
  3. 简述 在tcp协议中,双方建立连接的时候是需要三次握手。这个连接建立需要一方主动打开,另外一方被动打开的。下图为建立连接图解。
  4. 网络请求建立连接,经历三次握手流程
    a 第一次握手
    在第一次"握手"时,客户端向服务端发送SYN标志位,目的是与服务端建立连接。Seq代表sequence,number(发送数据流序号), 例如:Seq的值是5,说明在数据流中曾经一共发送了 1, 2, 3,4 这4次数据。而在本次"握手"中, Seq的值是0,代表客户端曾经没有给服务端发送数据。另外Len=0也可以看出来是没有数据可供发送的,客户端仅仅发送一个SYN标志位到服端代表要进行连接。

b 第二次握手

第二次"握手"时,服务端向客户端发送 SYN ACK 标志位,其中ACK标志位表示是对收到的数据包的确认,说明服务端接收到了客户端的连接。ACK的值是1,表示服务端期待下一次从客户端发送数据流的序列号是1,而Seq=0代表服务端曾经并没有给客户端发送数据,而本次也没有发送数据,因为Len=0也证明了这一点。

c 第三次握手

第三次“握手”时,客户端向服务端发送的ACK标志位为1, Seq的值是1。Seq=l代表这正是服务端所期望的Ack=1。Len=0说明客户端这次还是没有向服务端传递数据,而客户端向服务端发送ACK 标志位为1的信息,说明客户端期待服务端下一次传送的Seq的值是1。

  1. 为什么要进行三次握手 为了防止服务器端开启一些无用的连接,增加服务器开销。以及防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。4.4 TCP协议中,连接断开时候(四次挥手)
  2. 四次挥手 即TCP连接的释放(解除)。连接的释放必须是一方主动释放,另一方被动释放。以下为客户端主动发起释放连接的图解:
    undefined 简述流程undefined a 客户端到服务端,我要关了。undefined b 服务端到客户端,好的,我收到了。undefined c 服务端到客户端,我也关了。undefined d 客户端到服务端,好的,收到。
  3. 四次挥手执行流程
    a 第一次挥手 在第一次"挥手"时,客户端到服务器发送标志位FIN ACK,告知服务端客户端关闭了。Seq=1表示本次数据流的序号为1,Ack=1表示客户端期望服务端下一次发送的数据流的序号为1。len=0,说明没有数据传输到服务端。

b 第二次挥手

在第二次"挥手"时,服务端向客户端发送标志位ACK,Seq=1代表的正是客户端想看的Ack=1。Ack=2表示服务端期望下一次客户端发送的数据流的序号为2。len=0,说明没有数据传输到客户端。

c 第三次挥手

在第三次"挥手"时,服务端向客户端发送标志位FIN ACK,告知客户端服务端关闭了。Seq=1代表的正是客户端想看的Ack=1。Ack=2表示服务端期望下一次客户端发送的数据流的序号为2。len=0,说明没有数据传输到客户端。

d 第四次挥手

在第四次"挥手"时,客户端向服务端发送标志位ACK,告知服务端客户端已经收到服务端关闭信息。Seq=2

代表的正是服务端想看的Ack=2,ACK=2表示客户端期望下一次服务端发送的数据流的序号为2。

注意 BIO存在问题

1、客户端已经连接服务端,尚未发送数据,read阻塞

2、新的客户端无法正常连接

解决办法

1、线程解决(mysql客户端连接服务器)

2、线程池解决(线程池泄露)

3、NIO解决

4、websocket

五 NIO编程

5.1 概述

NIO又称为非阻塞IO,是JDK1.4提出的新的IO模型

5.2 组件详细介绍

5.2.1 Buffer(缓冲区)

  1. 概述 按照物理区分为:直接缓冲区和堆字节缓冲区。undefinedBuffer模式:写模式和读模式
  2. 缓冲区执行原理undefineda 三个属性(Buffer的三个属性)undefined capacity(容量)、position(位置)、limit(限制)undefined

b 写模式

capacity:数组中可以存储元素的个数

position:下一次可插入元素位置,默认值为0,每添加一个元素都向后移动一位,最大值:capacity - 1

limit:在写的模式下,limit表示第一个不可写的位置(默认第一个不可写的位置,应该是数组容量值得下一个位置,即默认值为capacity)

c 读模式

capacity:数组中可以存储元素的格数。

position:Buffer由写模式变化为读模式,position会从置0,在进行读取数据时,position向前移动到下一个可读的位置。

limit:第一个不可读位置,当写模式切换到读模式,limit设置写模式下的position值。即能读到之气那所有写入的数据。

5.2.2 Channnl(通道)

1 概述

类似于流进行数据传输,但是和流不同。流是单向的,大部分功能比较单一,要么进行读要么进行写。

通道的使用必须要结合Buffer。

5.2.3 Selector(选择器)

  1. 概述 每一个通道都存在一个线程对其处理。在高并发情况下,就会存在很多通道,就会创建很多线程对象,造成内存占用率升高,增加cpu在多个线程之间切换的时间。因此不使用高并发场景下。
  2. NIO使用通道的改良undefined我一个线程处理多个任务通道的任务的机制,在NIO中成为多路复用。使用后IO复用后,只需一个线程能对多个通道进行处理,对于高并发的业务场景有优势。补充如下:undefined 线程数随着通道多少进行动态的增减来进行适配。多路复用的核心目的使用最少的线程数去操作更多的通道。创建线程的个数根据通道个数来决定。每注册1023个通道就创建一个线程
    5.2.4 NIO实例public class SocketNioServer { public static void main(String[] args) throws Exception { //定义通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //绑定地址 serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 8080)); //设置为非阻塞模式 serverSocketChannel.configureBlocking(false); //开启一个选择器 Selector selector = Selector.open(); //注册 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { System.out.println("等待连接,阻塞中....."); int count = selector.select(); if (count != 0) { Set<SelectionKey> selectionKeys = selector.selectedKeys(); //遍历集合 Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); //客户端已经连接,尚未发送数据 if (selectionKey.isAcceptable()) { System.out.println("客户端已经连接,尚未发送数据...."); //获取通道 ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel = ssc.accept(); //设置非阻塞 socketChannel.configureBlocking(false); //注册到选择器 socketChannel.register(selector, SelectionKey.OP_READ); } //任务就绪 else if (selectionKey.isReadable()) { System.out.println("客户端成功发送数据"); //获取通道 SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); //读取信息 ByteBuffer buffer = ByteBuffer.allocate(1024); int read = socketChannel.read(buffer); while (read > 0) { //切换缓冲区的模式 buffer.flip(); System.out.println(new String(buffer.array(), 0, read)); //清除缓冲区 buffer.clear(); read = socketChannel.read(buffer); } socketChannel.close();//释放资源 } iterator.remove(); } } } } }

u1fbpfcp-watermark.image)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一 基础
    • 1.1 概述
      • 1.2 软件架构
        • 1.3 基本概念(通信协议/ip/端口)
        • 二 计算机通信分层
          • 2.1 七成模型、TCP/IP协议族、TCP、IP这些是不是同一个东西?
            • 2.2 访问淘宝经历了网络流程
            • 三 网络传输层解析
              • 3.1 Socket是什么?
                • 3.2 Socket通信流程
                  • 3.3 网络传输层的TCP协议详解
                  • 四 TCP断开和连接的原理刨析(三次握手和四次挥手)
                    • 4.1 数据在传递过程中,字段解释
                      • 4.2 BIO
                        • 4.2.1 BIO代码实现
                        • 4.2.2 BIO中API讲解
                    • 五 NIO编程
                      • 5.1 概述
                        • 5.2 组件详细介绍
                          • 5.2.1 Buffer(缓冲区)
                          • 5.2.2 Channnl(通道)
                          • 5.2.3 Selector(选择器)
                      相关产品与服务
                      物联网通信
                      腾讯云物联网通信(Internet of Things Hub, IoT Hub)旨在提供一个安全、稳定、高效的连接平台,帮助开发者低成本、快速地实现“设备-设备”、“设备-用户应用”、“设备-云服务”之间可靠、高并发的数据通信。物联网通信平台不仅可以实现设备之间的互动、设备的数据上报和配置下发,还可以基于规则引擎和腾讯云产品打通,方便快捷地实现海量设备数据的存储、计算以及智能分析。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档