• 【网络编程详解】


    在这里插入图片描述

    🌈个人主页努力学编程’
    个人推荐
    c语言从初阶到进阶
    JavaEE详解
    数据结构
    学好数据结构,刷题刻不容缓点击一起刷题
    🌙心灵鸡汤总有人要赢,为什么不能是我呢
    在这里插入图片描述

    🔥🔥🔥网络编程

    对于我们之前的编程,基本上都是基于本地机器的运行代码,但是在实际开发的时候,基本上都会有两大部分组成,特别是一些软件的开发,一般会有客户端和服务器,在编写这部分代码的时候,我们的代码要连接网络才能和其他的机器连接.下面给大家讲解一些关于网络的一些比较重要的知识.

    ⭐⭐⭐IP地址

    对于每个每个电脑来说,我们可以进行联网操作,如果我们想要在整个互联网中快速找到这台机器的位置,就会涉及到一个非常重要的知识-IP,本质上来说IP就是这台电脑在互联网中的位置,我们要想找到一台机器的位置,就必须知道其IP地址.

    这里教大家如何查看自己电脑的IP的位置

    • 在设置中搜索网络设置
    • 点击网络连接属性即可(win11)

    在这里插入图片描述
    或者win+R,输入cmd,在cmd中输入命令:ipconfig,也可以得到IP地址.
    在这里插入图片描述

    ⭐⭐⭐端口号

    我们有了IP地址,得到了每台机器的地址,在每台机器中,都会有接收数据,和发送数据的过程.端口就是记录每个接收数据和发送数据的进程,所以端口号本质: 端⼝号⽤于定位主机中的进程

    就比如发送快递的时候,不但要填写收货地址(IP地址),还要填写收件人(端口)

    此时虽然我们已经可以定位到一个电脑的IP地址,和端口(机器中的唯一的进程),但是网络通信的时候,我们传输数据的时候,都是将数据转换为0101这样的二进制的数据,然后传给另一台机器,但是接收的一方,如何由一堆的二进制代码,判断此时传输的数据到底是文本文件还是视频,还是图片,所以我们就得约定一套固定的东西来约定一下这些东西-协议

    ⭐⭐⭐协议

    协议的作用就是为了在进行网络通信的时候,使每台电脑能够按照同一套规则进行数据的解析,这样就会让每一台电脑的数据都可以被其他的电脑接受和解析.总而言之,协议就是对于如何进行网络通信做了一个约定

    由于网络通信的整个过程的细节非常庞大,如果只使用一个协议,就会导致这个协议结构复杂化,且有了高耦合的问题,所以就会对协议进行分层,每一层只干一个/一类问题,

    OSI七层模型:
    在这里插入图片描述

    这种分层模式只存在于教科书中,并没有在实际应用中大量采用,在实际场景中我们最常用的是TCP/IP五层网络模型.

    在这里插入图片描述
    对于这五层模型,我们必须要理解,并最好可以熟练的讲出来,这也是我们面试的时候的一个高频考点.

    1. 应用层: 针对特定应用的协议
      在这里插入图片描述
    2. 传输层:传输层只关注网络通信的起点和终点,并不关心其中的细节,
    3. 网络层:进行网络通信的路径规划,同时还要负责地址的管理.
    4. 数据链路层:对于上面规划好的路线进行具体的实现,并对路线的具体过程有简单的记录
    5. 物理层:描述的是硬件层面需要满足怎样的条件,例如(网线有8根线)

    而对于程序员来说我们可以干预的只有应用层,其他的都是交给操作系统或者硬件设备.

    ⭐⭐⭐网络设备所在的分层:

    • 对于⼀台主机,它的操作系统内核实现了从传输层到物理层的内容,也即是TCP/IP五层模型的下四层;

    • 对于⼀台路由器,它实现了从⽹络层到物理层,也即是TCP/IP五层模型的下三层;

    • 对于⼀台交换机,它实现了从数据链路层到物理层,也即是TCP/IP五层模型的下两层;

    • 对于集线器,它只实现了物理层;

    🔥🔥🔥封装

    对于网络通信的时候,如何传输数据的,这里一共有两个过程,封装和分用.

    举个例子:
    你使用QQ发送了一个hello给你的同学,此时你在输入框中输入字符串之后,数据就会被打包为一个应用层数据包,里面可能会有你的QQ号,接受者的QQ号,消息的发送时间,消息的内容…
    在这里插入图片描述

    然后应用层数据包就会以参数的形式被传递给传输层API调用,进入传输层,在传输层中进一步对数据进行包装,称为一个传输层数据包(传输层这里有很多协议,这里使用UDP演示).
    在这里插入图片描述

    进一步传输层数据包也会调用网络层的API,进入网络层,在网络层中也有很多的协议,这里我们以IPv4为例,在日常开发中如果没有强调的话,说的都是IPv4, IPv6还没有大量普及…然后对数据作进一步的加工处理:
    在这里插入图片描述

    然后进一步调用数据链路层的API,进入数据链路层,这里的协议主要是以太网,(我们平时的网线就是这个),对数据作进一步的加工-添加以太网帧头帧尾.
    在这里插入图片描述
    最后数据进入到物理层,将二进制数据转化为光信号,电信号这样的数据传输给真正的物理硬件…

    我们上述都是在消息发送者的角度观察的,现在消息发出去,进入接受者视角,这个过程,其实和我们上述的过程刚好是相反的,对数据一步一步进行解析,这道最后进入应用层展示接受到的数据.

    🔥🔥🔥网络套接字

    操作系统给应用程序提供的API(传输层给应用层提供的API),即socket api
    接下来我们就学习的是操作系统给到我们提供的socket(Java版)
    这里的socket api提供了两个不同版本的api, UDP, TCP,

    这里也有一个经典的面试题:UDP和TCP的区别:

    • TCP:有连接,可靠传输,面向字节流,双全工.
    • UDP:无连接,不可靠传输,面相数据报,双全工.
    1. 有无连接: 此处谈到的连接,并不是物理层面的连接,而是一种"抽象" 的连接.通信对方都保存了对方的信息,这就相当于"有连接",如果没有保存对方的信息,就表示的是"无连接"
    2. 是否可靠传输: 这里的可靠传输,并非是只100%可以到达对方,而是尽可能 相对来说不可靠传输:就是完全没有考虑是否能够达到对方~
      TCP:内置了一些机制,能够保证,可靠传输.
    • 感知到对方是不是收到了
    • 对方没有收到时,进行重试

    UDP则没有可靠性机制
    UDP则完全不管数据是否顺利传到了对方

    面相字节流:
    这里的字节流就和文件流/水流是一样的特点.

    我们可以一次从文件中读取100个字节,也可以一次读写50个字节…
    TCP可以一次读写100个字节,第二次50个字节…

    面向数据报:
    UDP每次传输数据的时候,都是以数据报为一个单位进行传输的.

    双全工:一个通信链表,可以发送数据/也可以接受数据(双向通信)
    预支对用的:单双工:一个通信链路,只能发送/只能接受(单向通信)

    🔥🔥🔥UDP和TCP的使用

    这里主要介绍一下UDP的使用,首先了解UDP的API

    DatagramSocket 代表一个socket对象(可以理解为网卡这种硬件设备的抽象表达形式),我们就可以后面利用 DatagramSocket 间接操作网卡.

    DatagramPacket代表一个数据报,里面的构造方法,可以出传递数据信息,IP地址以及端口号.

    我们想要简单实现一个网络编程的场景,就需要两个程序:

    1. UDP 服务器
    2. UDP 客户端

    主动发起通信的一方我们称为客户端,另一方就是服务器.

    🔥🔥🔥UDP实现网络编程

    这里我们模拟实现一个客户端给服务器发送一条短信 hello 的整个过程

    服务器代码:

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class UdpEchoServer {
        private DatagramSocket socket=null;
        public UdpEchoServer(int port) throws SocketException {
            socket=new DatagramSocket(port);
        }
    
        //通过 start 启动服务器的核心流程
        public void start() throws IOException {
            System.out.println("服务器启动!!!");
            while(true){
                //此处通过 "死循环" 不停地处理客服端的请求
    
                //1.读取客户端的请求并解析
                DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
                socket.receive(requestPacket);
                //上述的数据是二进制的形式出现的,后续的代码如果进行打印之类的处理操作
                //需要转成字符串才处理好
                String request=new String(requestPacket.getData(),0,requestPacket.getLength());
    
                //2. 根据请求计算相应,由于此处是回显服务器,响应的就是请求
                String response=process(request);
    
                //3.把响应写回到客户端
                DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
                        requestPacket.getSocketAddress());
    
                //4.把日志打印一下
                System.out.printf("[%s:%d] req=%s, resq=%s\n",requestPacket.getAddress(),requestPacket.getPort(),
                        request,response);
            }
        }
        public String process(String request){
            return request;
        }
    
        public static void main(String[] args) throws IOException {
            UdpEchoServer server=new UdpEchoServer(9090);
            server.start();
        }
    }
    
    

    客户端代码:

    import java.io.IOException;
    import java.net.*;
    import java.util.Scanner;
    
    public class UdpEchoClient {
        private DatagramSocket socket = null;
        private String serverIP;
        private int serverPort;
    
        public UdpEchoClient(String serverIP, int serverPort) throws SocketException {
            socket = new DatagramSocket();
            this.serverIP = serverIP;
            this.serverPort = serverPort;
        }
    
        public void start() throws IOException {
            System.out.println("启动客户端");
            Scanner scanner = new Scanner(System.in);
    
            while (true) {
                // 1. 从控制台读取到用户的输入.
                System.out.print("-> ");
                String request = scanner.next();
                // 2. 构造出一个 UDP 请求, 发送给服务器.
                DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                        InetAddress.getByName(this.serverIP), this.serverPort);
                socket.send(requestPacket);
                // 3. 从服务器读取到响应
                DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
                socket.receive(responsePacket);
                String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
                // 4. 把响应打印到控制台上.
                System.out.println(response);
            }
        }
    
        public static void main(String[] args) throws IOException {
            // UdpEchoClient client = new UdpEchoClient("47.108.28.88", 9090);
            UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
            client.start();
        }
    }
    
    
    
    
  • 相关阅读:
    MockingBird,手把手教你克隆您的声音,AI代言人,惊艳你的耳朵!
    Mysql数据库 3.SQL语言 DML数据操纵语言 增删改
    从零开始—仿牛客网讨论社区项目(一)
    C# 发送邮件
    视频知识点(17)- flv.js 实现播放本地视频文件的技巧
    React 安装使用 Less(详细流程,包含 webpack、craco 方式)
    Python学习九:使用进程和线程
    保姆级银河麒麟V10高级服务器离线安装mysql5.7数据库
    彻底搞懂内存屏障(下)
    git:删除上一次 commit 中的某个文件,并重新提交
  • 原文地址:https://blog.csdn.net/2301_76249062/article/details/140999303