网络原理初识

一、网络分层协议:
-OSI 七层协议
-TCP/IP 四(五)层协议

1.数据传输过程的5要素:(1)目标地址IP (2)目标端口 (3)源地址IP (4)源端口号 (5)协议类型
2、传输层:TCP/UDP
UDP:无连接,不稳定,面向数据报 Datagram
TCP(主流):有连接,稳定,面向数据流(应用层协议中的HTTP协议就是基于TCP/IP协议实现的)
3.UDP协议端格式:
在这里插入图片描述
UDP长度=UDP头部长度(8个字节)+数据长度。
UDP 一个包的最大理论长度=2的16次方 = 65536/1024=64KB
校验和是用来确定数据在传输过程中是否被篡改,也就是用来判断数据的正确性的。
4.
5.数据传输过程(封装、分用)
封装:从应用层到物理层的过程
分用:从物理层到应用层的过程

二、网络中的地址管理
1、IP(IPV4/IPV6)
(1)查看本机的IP:cmd -> ipconfig

IPV4:32位数值(0/1)组成
2.MAC:物理地址、网卡地址
cmd -> ipconfig /all
在这里插入图片描述
三、UDP编程
例:智能机器人

/**
 * UDP服务器端
 */
public class UDPServer {
    private static final int port = 9001;
    //数据最大长度
    private static final int bleng = 1024;
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(port);
        System.out.println("服务器端已启动");
        while (true) {
            DatagramPacket client = new DatagramPacket(
                    new byte[bleng],
                    bleng
            );
            socket.receive(client);
            String msg = new String(client.getData());
            System.out.println("接受客户端的消息:"+msg);
            String str = msg.replace("吗?",".");
            DatagramPacket serMsg = new DatagramPacket(
                    str.getBytes(),
                    str.getBytes().length,
                    client.getAddress(),
                    client.getPort()
            );
            socket.send(serMsg);
        }
    }
}
/**
 * 客户端
 */
public class UDPClient {
    private static final int port = 9001;
    private static String ip = "127.0.0.1";
    private static final int bleng = 1024;
    public static void main(String[] args) throws IOException {
        DatagramSocket client = new DatagramSocket();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("我:");
            String msg = sc.nextLine();
            DatagramPacket clientMsg = new DatagramPacket(
                    msg.getBytes(),
                    msg.getBytes().length,
                    InetAddress.getByName(ip),
                    port
            );
            client.send(clientMsg);
            DatagramPacket socketMsg = new DatagramPacket(
                    new byte[bleng],
                    bleng
            );
            client.receive(socketMsg);
            String str = new String(socketMsg.getData());
            System.out.println("对方:"+str);
        }
    }
}

四、将项目发布到服务器上
例:UDP服务器发布:
1、在这里插入图片描述
2、build artifacts
3、在Xftp中引入jar包,在xshell中使用命令:java -jar xxx.jar
五、TCP编程

public class TCPServer {
    private static final int port = 9002;
    public static void main(String[] args) throws IOException {
        //创建并启动服务器端
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("服务器端已启动");
        //等待客户端的连接
        Socket clientSocket = serverSocket.accept();
        System.out.println(String.format("已有客户端的链接,IP:%s,端口号:%d",
                clientSocket.getInetAddress().getHostAddress(),clientSocket.getPort()));
        //try-resource:自动执行close操作
        try(
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(clientSocket.getInputStream()));
                BufferedWriter writer = new BufferedWriter(
                        new OutputStreamWriter(clientSocket.getOutputStream()))
        ) {
            while (true) {
                String msg = reader.readLine();
                System.out.println("接收到客户端的消息:" + msg);

                String serMsg = "我收到了";
                writer.write(serMsg + "\n");
                writer.flush();
            }
        }
    }
}

public class TCPClient {
    private static final String ip = "127.0.0.1";
    private static final int port = 9002;
    public static void main(String[] args) throws IOException {
        //创建并启动客户端,连接服务器端
        Socket socket = new Socket(ip,port);
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
             Scanner sc = new Scanner(System.in)
        ){
            while (true) {
                System.out.println("->");
                String msg = sc.nextLine();
                writer.write(msg+"\n");
                writer.flush();
                String serMsg = reader.readLine();
                if (serMsg != null) {
                    System.out.println("服务器端返回:" + serMsg);
                }
            }
        }
    }
}

六、HTTP协议
实现HTTP服务器的关键是:遵循HTTP协议
request:1.首行(方法类型 URI HTTP版本号)
2.head
3.空行
4.body
response:1.首行(HTTP版本号 状态码 状态描述符)
2.head(Content-type:text/html Content-Length)
3.空行
4.返回信息

/**
 * 自定义 HTTP 服务器
 */
public class MyHttp {
    private static final int port = 9004;
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("服务器端已启动~");
        Socket socket = serverSocket.accept();

        try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))
        ) {
            //得到首行信息request
            String firstLine = reader.readLine();
            String[] firstLineArr = firstLine.split(" ");
            String method = firstLineArr[0];//方法类型
            String uri = firstLineArr[1];//uri
            String httpVersion = firstLineArr[2]; //HTTP版本号
            System.out.println(String.format("首行信息 -> 方法类型:%s,uri:%s,HTTP版本号:%s",
                    method,uri,httpVersion));
            //构建返回内容
            String content = "";
            if (uri.contains("404")) {
                content = "<h1>没有找到此页面</h1>";
            } else if (uri.contains("200")) {
                content = "<h1>你好,世界</h1>";
            }
            //内容输出response
            writer.write(String.format("首行信息 -> HTTP版本号:%s,200,ok",httpVersion+"\n"));
            writer.write("Content-type: text/html;charset=utf-8\n");
            writer.write("Content-Length: "+content.getBytes().length+"\n");
            writer.write("\n");
            writer.write(content);
            writer.flush();
        }
    }
}

七、TCP/IP
(一)传输层
1.端口号:找到应用程序
最大端口号:0-65535
端口号分类:
知名端口号 0-1023(FTP:21,SSH:22,Telnet:23,HTTP:80,HTTPS:443,MySQL:3306,tomcat:8080,DNS:53)
动态端口号:1024-65535
2.面向字节流
创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区。
(1)调用write时, 数据会先写入发送缓冲区中;
(2)如果发送的字节数太长, 会被拆分成多个TCP的数据包发出;
(3)如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或者其他合适的时
机发送出去;
(4)接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;
(5)然后应用程序可以调用read从接收缓冲区拿数据;
(6)另一方面, TCP的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读
数据, 也可以写数据. 这个概念叫做 全双工。
3.粘包,半包问题
TCP面向数据流,流是没有边界的,可能会造成粘包,半包问题
粘包,半包问题的解决方案:
(1)使用\n作为流的结束符,这样流就有边界了,就能正常的收、发消息了
(2)每次发送固定大小的流信息,这样也能确定每个数据边界。
byte[] bytes = new byte[1024];//将传送的消息转化为字节数组msg.getBytes()。
4.TCP异常处理方式
(1)可挽救:电脑重启或结束进程的时候,它会发送 FIN 请求,和正常关闭 TCP 是没有什么区别的。
(2)不可挽救 : 电脑掉电/网线中断:TCP 保活定时器,会定时检测对方是否在线如果检测的结果是没有任何响应的,说明已经掉下,直接释放连接。
(二)网络层
在复杂的网络格式中确定一个合适的路径。
1.IP 协议

八、TCP特性
1.确认应答(ACK)机制(保障 TCP 稳定的核心机制)
2.超时重传机制
超时重发的策略:
策略1:发送不会以固定的频率发送。策略1采取的是悲观策略,如果第一次发送消息失败了,那么大概率第二次也会失败,所以TCP会以指数级超时时间增长的频率去发送消息。
策略2:如果经历了一定的重试次数,消息还没有得到应答,就会停止发送。
3.连接管理机制
3次握手(3次通讯)
4次挥手(4次通讯)

ESTABLISHED:表示3次握手已经完成,可以进行数据的传输了。

服务器端先变为CLOSED状态,客户端的TIME_WAIT会等待 2 MSL(最大超时时间)状态才会变为CLOSED。
2 MSL = ACK 最大超时时间(1 MSL) + 对方发送给它消息的一个最大等待时间(1 MSL)。
4.滑动窗口(始终保持这样大小的容量进行信息传递)
如果16位的滑动窗口大小位0,那么发送端就不会发送消息给接收端。
一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能。
在这里插入图片描述
如果出现了丢包, 如何进行重传? 这里分两种情况讨论.
情况一: 数据包已经抵达, ACK被丢了。
在这里插入图片描述
这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认。
ACK=6000 的含义:告诉主机A,我成功的收到了 0~6001
ACK返回的值是当前(主机B_右边)接收缓冲区的下一个值(最大连续值)
情况二: 数据包就直接丢了。

当前面的数据被正常补齐之后,返回的ACK是最大值,这种机制叫做“快重传”。
5.流量控制(以结果(接收缓冲区的大小)为导向进行数据的传递)
接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度, 这个机制就叫做流量控制
TCP会以固定的频率发一个检测包,用来检测接收区空间的大小,当接收缓冲区不为0时,消息才会恢复发送。
6.拥塞控制
当前时间的网络来动态调整收发的频率就叫拥塞控制。
在这里插入图片描述
快重传:ACK始终返回是都是最大值。
7.延迟应答
窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。
延迟应答策略:
(1)每隔一段时间(固定时间)延迟应答一次。(一定程度上加速发送消息的速度)
(2)每隔n次(2次)延迟应答一次。
延迟应答注意事项:延迟应答的时间(200MS)小于超时重传的时间(500MS)。
8.捎带应答
是针对于延迟应答的性能优化。
在这里插入图片描述
面试问题
1.TCP,UDP的区别:
UDP:无连接,不稳定,面向数据报 ;
没有发送缓冲区,只有接收缓冲区。
TCP:有连接,稳定,面向数据流;
既有发送缓冲区,又有接收缓冲区。
UDP 和 TCP 的使用场景不同,如果对稳定性要求比较高,应该选用 TCP ;如果对消息丢失不敏感,要求性能比较高,那么可以考虑 UDP.
2.UDP 一个包的最大理论长度=2的16次方 = 65536/1024=64KB,如果 UDP 编程的时候的数据大小大于64KB会怎摸样?
(1)在 应用层进行数据包的拆分和组合。
(2)大于64KB不用处理,交给TCP/IP协议去处理,它会在网络层进行分包和组包(缺点:一个包丢失整组包舍弃)。
3.两次握手可不可以?
不可以,不能证明客户端的接受能力和服务器端的发送能力。

4.三次挥手可以吗?
有可能可以。
对应到程序:接收缓冲区没有数据了,那么就可以直接关闭连接。
5.如果发现服务器端存在大量的CLOSED_WAIT 说明程序有问题?
服务器没有正确的关闭 socket, 导致四次挥手没有正确完成. 这是一个 BUG. 只需要加上对应的 close 即可解决问题
6.如何使用 UDP 实现稳定的消息传输?
在应用层参考TCP实现稳定性的特性来设计UDP。
TCP 保证稳定性:(1)确认应答 (2)超时重传 (3)连接管理 (4)流量控制 (5)拥塞控制
保证性能:(1)滑动窗口 (2)延迟应答 (3)捎带应答
7.当在浏览器中输入URL 后会发生什么?
(1)浏览器会先检查你的URL地址是否输入正确。
(2)浏览器会检查URL有没有缓存信息,如果有缓存则取缓存。(解决方案:强刷,改变URL地址)
(3)进行DNS解析,拿到IP地址进行访问。
(4)TCP三次握手。(流程)
(5)HTTP协议的发送,发送request(首行,head,空行,body)对象。
(6)服务器端接收到请求并且进行相应的业务处理。
(7)服务器端将结果返回给客户端。
(8)浏览器拿到返回的结果并调用浏览器的内核实现前端页面的渲染。
(9)进行TCP四次挥手。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值