美文网首页
远程通信协议原理

远程通信协议原理

作者: 剑道_7ffc | 来源:发表于2020-02-27 19:40 被阅读0次

一个 http 请求的整个流程

负责域名解析的 DNS 服务

DNS服务提供通过域名来找到对应的ip,使用域名的原因是域名比ip地址更好记忆。


image.png

加速静态内容访问速度的 CDN

CDN是一种内容分发网络(Content Delivery Network),将相对稳定的内容放在离用户最近的内容,这样做的好处是用户的访问速度会更快和节省整个广域网的消耗,我们一般会把静态的文件如图片,脚本和静态文件放在CDN中

HTTP 协议通信原理

HTTP是应用层协议,TCP/UDP是传输层的协议。


image.png
请求发起过程,在 tcp/ip 四层网络模型中所做的事情不停的封装如下图

TCP头:根据端口号定位进程,用于点对点传输
IP头:根据ip定位主机,用于段对端传输
MAC头:根据mac地址定位网卡


image.png

注:目的mac地址的获取
通过ARP(Adress Resolve Protocol)可以根据已知ip获取mac地址

接收端收到数据包以后的处理过程不停的解封装如下图
image.png

注:为什么有了mac地址还需要ip
mac地址表示人的身份证,全局唯一;
IP地址表示一台机器在网络中的位置类似于城市名+道路号+门牌号

TCP/IP 的分层管理

分层的原因:降低复杂度和增加灵活性

分层负载(OSI的七层模型)

对于分层来讲,可以有下层没上层,但不可以没上层无下层如路由器。

二层负载均衡

针对的是MAC地址,特点:一个集群提供一个虚拟MAC地址,通过改写报文的目的MAC地址来请求到具体的服务器

三层负载均衡

针对的是IP,特点:一个集群提供一个虚拟ip,通过负载均衡算法来请求到具体的服务器

四层负载均衡

针对的是传输层(IP + 端口号),特点:一个集群提供一个虚拟ip,通过修改数据包的地址信息(IP + 端口号)来请求到具体的服务器

七层负载均衡

针对的是应用层,特点:通过虚拟的url或主机名来接受请求,然后在分配到具体的服务器

TCP/IP 协议的深入分析

TCP类似于打电脑,UDP协议类似于校园广播

TCP 握手协议

TCP的可靠性是连接的建立,通过三次握手来建立连接,即代码的connect的过程


image.png

ACK 可设为 1/0,1表示确认号有效,0表示确认号无效。
SYN:用在连接建立的过程
Seq:表示初始序号
第一次:客户端发送完毕:客户端进入SYN_SEND 状态
第二次:服务端发送完毕:服务端进入SYN_RCVD 状态
第三次:客户端发送完毕:客户端进入ESTABLISHED状态
服务端接受完毕:服务端进入ESTABLISHED状态

SYN 攻击

客户端伪造大量发送不存在的ip包(源ip),服务器确认,等待客户端的确认恢复,从而导致超时和正常的syn请求因队列满而被丢弃。

TCP 四次挥手协议

TCP协议是全双工的,对应的代码是客户端和服务端的close操作。


image.png

FIN:被用来释放连接,它表示发送方已经没有数据要传输了,但是可以继续接收数据
第一次挥手:客户端发送完成:客户端进入 FIN_WAIT_1 状态
第二次挥手:服务端发送完成:服务器端进入 CLOSE_WAIT 状态,客户端接收完成:客户端进入 FIN_WAIT_2 状态,服务端准备关闭
第三次挥手:服务端发送完成:服务端进入LAST_ACK,服务端开始关闭
第四次挥手:客户端发送完成:客户端进入TIME_WAIT,客户端在ZMSL的时间内,没有接收到ACK包,则自动进入CLOSED状态
服务端接收完成:服务端进入CLOSED状态

问题

为什么连接的时候是三次握手,关闭的时候却是四次握手?

三次握手是因为ACK和SYN可以一起发送;
四次挥手是因为ACK和FIN不可以一起发送,第二次挥手表示对客户端的确认,但服务端关闭没有准备好,第三次挥手表示服务端关闭准备好了

为什么 TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSE状态?

因为网络是不可靠的,会导致最后一个ACK会出现丢失的情,从而引发服务端的超时重传。

使用协议进行通信

通过socket实现网络通信

基于 TCP 协议实现通信

客户端

    public static void main(String[] args)
    {
        Socket socket=null;
        PrintWriter out=null;
        try {
            socket=new Socket("127.0.0.1",8080);
            out=new PrintWriter(socket.getOutputStream(),true);
            out.println("Hello, Mic");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(out!=null){
                out.close();
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

服务端

    public static void main(String[] args)
            throws IOException {
        ServerSocket serverSocket = null;
        BufferedReader in = null;
        try {
            /**
             * 通过构造器来绑定这个服务(bind),来监听端口
             * ip:来定位网卡,因为一个机器中会有多个网卡,也会有多个ip
             * port:定位应用程序
             */
            serverSocket = new ServerSocket(8080);

            //阻塞服务端
            Socket socket = serverSocket.accept();

            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println(in.readLine());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                serverSocket.close();
            }
        }
    }

基于 TCP 实现双向通信对话功能

客户端

    public static void main(String[] args) {
        try {
            //找到目标的ip和端口
            Socket socket=new Socket("localhost",8080);

            //在当前链接上写入输入
            PrintWriter out=new PrintWriter(socket.getOutputStream(),true);
            //控制台的输入流
            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
            //拿到输入流
            BufferedReader in=new BufferedReader(new InputStreamReader
                    (socket.getInputStream()));

            String readline=sin.readLine(); //获得控制台的输入
            while(!readline.equals("bye")){
                out.println(readline);

                System.out.println("Server:"+in.readLine());
                readline=sin.readLine(); //重新获取
            }


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端

    public static void main(String[] args) {
        ServerSocket serverSocket=null;

        try {
            //服务端一定需要去监听一个端口号,ip默认就是本机的ip地址
            serverSocket=new ServerSocket(8080);

            Socket socket = serverSocket.accept();

            //拿到输入流(阻塞, read/write阻塞)
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //输出流
            PrintWriter printWriter=new PrintWriter(socket.getOutputStream());
            //通过控制台拿到数据
            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Client:"+in.readLine()); //获得输入流的信息
            String line=sin.readLine(); //获得控制台输入的数据
            while(!line.equals("bye")){
                printWriter.println(line); //写回到客户端
                printWriter.flush();

                System.out.println("client:"+in.readLine()); //读取客户端传过来的数据
                line=sin.readLine(); //重新读取控制台的数据
            }

            System.out.println(in.readLine()); //获得客户端的输入信息

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

socket通信模型

image.png

理解TCP的通信原理及IO阻塞

了解 TCP 协议的通信过程

image.png

send():将数据发送到Tcp发送缓冲区
recv():将数据从Tcp接收缓冲区中读取
若TCP接收缓冲区满了,则滑动窗口关闭。

滑动窗口协议

用于流量控制
在线演示
https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/selective-repeat-protocol/index.html

发送窗口

发送端可以不等待应答而连续发送的最大幀数称为发送窗口的尺寸。

接收窗口

接收方允许接收的幀的序号表,凡落在接收窗口内的幀,接收方都必须处理,落在接收窗口外的幀被丢弃。

理解阻塞到底是什么回事

阻塞指一个服务端只能处理一个客户端的请求,其他客户端的请求阻塞。

一个客户端对应一个线程

缺点:线程的个数受限,若线程过多时,增加cpu上下文的切换


image.png

非阻塞模型

阻塞IO

阻塞IO是当客户端的数据从网卡缓冲区复制到内核缓冲区之前,服务端会一直阻塞。以socket接口为例,进程空间中调用 recvfrom,进程从调用 recvfrom 开始到它返回的整段时间内都是被阻塞的,因此被成为阻塞 IO 模型


image.png
非阻塞 IO

非阻塞 IO 模型的原理很简单,就是进程空间调用 recvfrom,如果这个时候内核缓冲区没有数据的话,就直接返回一个 EWOULDBLOCK 错误,然后应用程序通过不断轮询来检查这个状态状态,看内核是不是有数据过来。


image.png
I/O 复用模型

I/O 多路复用的本质是通过一种机制(系统内核缓冲 I/O 数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作

相关文章

  • 远程通信协议原理

    一个 http 请求的整个流程 负责域名解析的 DNS 服务 DNS服务提供通过域名来找到对应的ip,使用域名的原...

  • 远程通信协议

    在分布式架构中,有一个很重要的环节,就是分布式网络中的计算机节点彼此之间需要通信。 HTTP 协议通信原理 说到通...

  • Netty实现RPC的思路

    RPC RPC(Remote Procedure Call)远程过程调用,是一个计算机通信协议,可以实现远程调用远...

  • websocket + node.js

    websocket的原理和应用 在继续本文之前,让我们了解下websocket的原理: websocket通信协议...

  • 远程通信协议基础

    一个http请求image.png 应用层协议:httpftpsmtptelnet OSI七层网络模型image....

  • 【图文动画详解原理系列】10.网络通信协议与IO

    【图文动画详解原理系列】10.网络通信协议与IO

  • Go语言之GRPC

    RPC:远程调用框架(Remote Procedure Call), 远程调用原理: 比如 A (client) ...

  • 分别写远程系统命令执行与代码执行漏洞原理

    分别写远程系统命令执行与代码执行漏洞原理 远程命令执行原理:应用系统从设计上需要给用户提供指定的远程命令操作的接口...

  • RPC 与 http

    2.1.认识RPC RPC,即 Remote Procedure Call(远程过程调用),是一个计算机通信协议。...

  • APNS消息推送的实现(完整步骤)

    1. 原理及代码实现 iOS远程推送原理及实现过程 苹果远程推送通知 APNs 详解,官方,iOS | Swift...

网友评论

      本文标题:远程通信协议原理

      本文链接:https://www.haomeiwen.com/subject/kgwxhhtx.html