【TCP/IP协议】

TCP/IP协议

1. 应用层

应用层是我们作为程序猿最经常打交道的。在写代码的时候会有两方面:

  1. 使用现成的应用层协议,最常见的就是http
  2. 自己约定一个应用层协议

对于第二点,我们实现一个简单的网络计算器。

自定义协议 请求格式为:num1;num2;operator(操作数1,操作数2 ,操作符)

客户端要求用户输入两个参与运算的整数,再输入一个要进行运算的方式(+ - * /),客户端将这些信息发送给服务器,服务器将计算的结果返回给客户端。自定义协议具体的协议方式有很多种,这里我们使用最简单粗暴的方式(文本+分隔符)

服务器代码

public class CalcServer {
    private DatagramSocket socket = null;

    public CalcServer(int port) throws SocketException {
        this.socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            String response = process(request);
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            String log = String.format("[%s;%d] 请求:%s  响应:%s",
                    requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
            System.out.println(log);
        }
    }

    private String process(String request) {
        //把请求还原成操作数和运算符
        String[] tokens = request.split(";");
        if (tokens.length != 3) {
            return "[请求格式错误]";
        }
        int num1 = Integer.parseInt(tokens[0]);
        int num2 = Integer.parseInt(tokens[1]);
        String operator = tokens[2] + "";
        int result = 0;
        if (operator.equals("+")) {
            result = num1 + num2;
        } else if (operator.equals("-")) {
            result = num1 - num2;
        } else if (operator.equals("*")) {
            result = num1 * num2;
        } else if (operator.equals("/")) {
            result = num1 / num2;
        } else {
            return "[请求格式错误,操作符不支持]";
        }
        return result + "";
    }

    public static void main(String[] args) throws IOException {
        CalcServer server = new CalcServer(9090);
        server.start();
    }
}

客户端代码

public class CalcClient {
    private DatagramSocket socket = null;
    private String serverIp;
    private int serverPort;

    public CalcClient(String serverIp, int serverPort) throws SocketException {
        this.socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }
    public void start() throws IOException {
        while (true) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入第一个操作数num1:");
            int num1 = scanner.nextInt();
            System.out.println("请输入第二个操作数num2");
            int num2 = scanner.nextInt();
            System.out.println("请输入操作符(+ - * / ):");
            String operator = scanner.next();
            String request = num1+";"+num2+";"+operator;
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println("计算结果为:"+response);
        }
    }

    public static void main(String[] args) throws IOException {
        CalcClient client = new CalcClient("127.0.0.1",9090);
        client.start();
    }
}
//客户端结果:
请输入第一个操作数num1:
5
请输入第二个操作数num2
9
请输入操作符(+ - * / )*
计算结果为:45
//服务器结果:
服务器启动
[/127.0.0.1;58855] 请求:5;9;*  响应:45

实际开发中,自定义协议除了刚才这种文本+分隔符的方式,大体分为两类

  1. 文本格式(把请求响应当成字符串来处理,处理的基本单位是字符)

    xml json等等

  2. 二进制格式(把请求响应当成二进制数据处理,处理的基本单位是字节)

    protobuffer thift 等等

2. 传输层

传输层是操作系统内核实现的,因此传输层协议一般都是指现成的协议

传输层协议主要有两个UPD 、TCP

2.1 UDP协议

特点:

  1. 无连接
  2. 不可靠传输
  3. 面向数据报传输
  4. 全双工

UDP协议段格式

在这里插入图片描述

在这里插入图片描述

2.2 TCP协议

特点:

  1. 有连接
  2. 可靠传输
  3. 面向字节流传输
  4. 全双工

TCP协议段格式

在这里插入图片描述

源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
32位序号/32位确认号:和下面的确认应答机制有关;
4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是
15 * 4 = 60 字节
6位标志位:
URG:紧急指针是否有效
ACK:确认号是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
16位窗口大小:和下面的滑动窗口机制有关
16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不
光包含TCP首部,也包含TCP数据部分。
16位紧急指针:标识哪部分数据是紧急数据;
40字节头部选项:暂时忽略;

TCP原理

TCP对数据传输提供了一些管控机制,主要体现在可靠性和效率两方面

这些机制和多线程的设计原则类似:保证数据传输可靠的前提下,尽可能的提高传输效率

在这里插入图片描述

在这里插入图片描述

3. 网络层

网络层核心协议:IP协议

IP协议头格式:

在这里插入图片描述

  • 4位版本号:指的是IP协议的版本,对于IPv4来说,就是4 (0100);
  • 4位首部长度:一位代表4个字节,4位表示的范围为0-15,所以IP首部长度最大为4*15=60字节
  • 8位服务类型:3位优先权字段(已经弃用),4位TOS字段和1位保留字段(必须置为0),4位TOS分表表示:最小延迟,最大吞吐量,最高可靠性,最小成本,这四者相互冲突,只能选择一个
  • 16位总长度:表示IP数据报整体占多少个字节,一个IP数据报最多64k,但是IP协议内置了分包组包功能,如果一个数据长度超过64k,IP协议就自动拆成多个数据报,接收方再重新组包
  • 16位标识(id):唯一的标识主机发送的报文,如果IP报文再数据链路层被分片了,那么每个片里面的这个id都是相同的
  • 3位标志:第一位保留,第二位为1表示禁止分片,这时如果报文长度超过MTU,IP模块就会丢弃报文,第三位表示更多分片,如果第三位为1,表示后面还有分片,如果为0,表示这是最后一个分片
  • 13位片偏移:描述当前分片在原报文中的哪个位置,值越小越靠前,值越大越靠后,
  • 标识,标志,片偏移都是用来辅助IP分包组包的
  • 8位生存时间:数据报到达目的地的最大报文跳数,每经过一个路由器,TTL-1,当TTL=0时,还没到达目的地,就会丢弃,TTL主要用来防止出现路由循环
  • 8位协议:标识上层协议(传输层协议)的类型,接收方分用的时候保证载荷数据内容要给相对应的传输层协议,
  • 16位首部校验和:使用CRC校验,判断头部是否损坏,
  • 32位源IP地址:表示发送方的IP地址
  • 32位目的IP地址:表示接收方的IP地址

IP协议核心功能:地址管理;路由选择

3.1 地址管理

IP地址由32个bit位表示,也就是42亿9千万多,这个数字,对于现在的互联网设备来说不太够用,但是理论上我们希望每台设备的IP地址都不能重复。解决这一问题主要有动态分配IP和NAT机制

动态分配IP:

设备接入网络就分配IP,没有接入网络就不分配IP,因为并不是全世界所有设备都同时联网。

NAT机制 (网络地址替换):

使用一个IP地址,代表一批主机。例如一个局域网内部的主机共同拥有一个外网IP,这些主机的IP称为局域网IP,也就是内网IP,局域网内部的IP在同一个局域网内部不能重复,两个不同的局域网可以使用重复的局域网IP,局域网IP只能在局域网内部使用

在这里插入图片描述

除了上图中的三类IP,其他IP地址都是外网IP,外网IP对应唯一的设备,并且不能重复

在这里插入图片描述

如果局域网内有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的IP都是相同的,NAT路由器如果判断数据应该转给局域网中哪个主机?

NAPT机制

在这里插入图片描述

这种IP+port的关联关系是由NAT路由器自动维护的,例如在TCP的情况下,建立连接时,就会生成这个表项,在断开连接后,就会删除这个表项

网段划分

IP地址分为两个部分:网络号和主机号

网络号标识网段,保证互相连接的两个网段具有不同的标识

主机号标识主机,同一网段(局域网)内,主机之间具有相同的网络号,但是必须有不同的主机号

特殊的IP地址:

  1. 主机号为全0,这个IP就表示网络号,表示当前这个网段
  2. 主机号为1,这个IP通常表示当前网段的网关,
  3. 主机号为全1,表示广播IP
  4. 127.* 环回IP,表示本机IP

具体使用子网掩码划分主机号和网络号,子网掩码格式和IP地址一样,也是32位的二进制数,左边是网络位用1表示,1的数目等于网络位的长度,右边是主机位,用0表示,0的数目等于主机位的长度

将IP地址和子网掩码进行按位与操作,得到的结果就是网络号,

将子网掩码二进制按位取反,再与IP地址进行按位与计算,得到的就是主机号

例如:

十进制二进制
IP地址180.210.242.13110110100.11010010.11110010.10000011
子网掩码255.255.248.011111111.11111111.11111000.00000000
网络号180.210.240.010110100.11010010.11110000.00000000
主机号0.0.2.13100000000.00000000.00000010.10000011

3.2 路由选择

路由选择也就是规划路径。IP数据报中包含了目的IP地址,由于网络环境错综复杂,虽然IP数据报自己要发往哪,但是它并不知道该怎么走,只能像"问路"一样,根据每个路由器中的路由表信息,来一步步的靠近目的地,

IP协议中,数据到达某个路由器之后,这个路由器并不知道网络整体的环境,这个路由器只知道和它相邻的设备信息,直到找到一个路由器,这个路由器包含了这个IP数据报的目的地址,这个IP数据报才能到达目的地址

4. 数据链路层

主要负责两个相邻节点之间数据的传输

MAC地址

  • 主机具有一个或多个网卡,路由器具有两个或者两个以上的网卡,其中每个网卡都有唯一的MAC地址
  • 网络通信即网络数据传输,本质上是网络硬件设备,将数据发送到网卡上,或从网卡接收数据
  • 硬件层面,只能基于MAC地址识别网络设备的网络物理地址

MAC地址用来识别数据链路层中相连的节点,一个MAC地址6个字节,一般使用16进制加冒号的形式表示 例如 08:00:27:03:fb:19,MAC地址在网卡出厂的时候就确定了,不能修改,虚拟机中的MAC地址不是真实的MAC地址,可能会冲突,也有些网卡支持用户配置MAC地址

广播数据报:发送一个广播数据报,表示对同网段所有主机发送数据报,广播数据报的MAC地址为FF:FF:FF:FF:FF:FF

数据链路层的重要协议:以太网

以太网不是一种具体的网络,而是一种技术标准,既包含了数据链路层的内容,也包含了一些物理层的内容,例如:规定了网络拓扑结构,访问控制方式,传输速率等

以太网帧格式:

在这里插入图片描述

目的地址和源地址:指的是MAC地址,目的地址是下一个节点的MAC地址,源地址是自己的MAC地址,长度48位

类型:两个字节,0800类型,表示数据部分是IP数据报;0806类型,表示ARP数据报;8035类型,表示RARP数据报;

46-1500 表示一个IP数据报的长度范围

帧尾:CRC校验和

MTU

MTU相当于发快递时对包裹尺寸的限制,这个限制是不同的数据链路对应的物理层,产生的限制

以太网帧中的数据长度最大1500字节,就是以太网的最大传输单元,也就是MTU,不同的网络类型有不同的MTU

MTU对IP协议的影响:由于数据链路层MTU的限制,对于较大的IP数据包要进行分包

在这里插入图片描述

在这里插入图片描述

MTU对UDP协议的影响

如果UDP数据报中的数据太多,就会在网络层分成多个IP数据报,任意一个IP数据报丢失,都会引起接收端网络层重组IP数据报失败,所以,如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了

MTU对于TCP协议的影响

TCP的一个数据报也不能无限大,还是受限于MTU,TCP的单个数据报的最大消息长度称为MSS,TCP在建立连接的过程中,通信双方会进行MSS协商,最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度,双方在发送SYN的时候,会在TCP头部写入自己能支持的MSS值,然后选择最小的作为最终MSS。

在这里插入图片描述

ARP协议

ARP协议并不是一个单纯的数据链路层协议,而是介于数据链路层和网络层之间的协议

在网络通讯时,源主机的应用程序直到目的主机的IP地址和端口号,但不知道目的主机的MAC地址

数据包首先是被网卡接收到,再去处理上层协议的,如果接收到的数据包的MAC地址与本机不符,直接丢弃,所以通讯前必须获得目的主机的MAC地址

ARP协议建立了主机IP地址和MAC地址的映射关系

ARP协议的工作流程

设备接入网络的时候,先在当前局域网中广播一个ARP请求,收到这个请求的设备返回ARP响应(包含设备的IP和MAC),接入网络的设备就把这样的关系保存起来,这个过程可能会周期性的进行,

在这里插入图片描述

源主机发送一个ARP请求,询问"IP地址是172.20.1.2的主机的MAC地址是多少",并将这个请求广播到局域网上,目的主机接收到广播的ARP请求后,发送一个ARP应答,包含自己的IP地址和MAC地址,每台主机都维护一个ARP缓存表,可以用arp-a命令查看,缓存表中表项有效期时间一般为20分钟,如果2-分钟内没有再次使用某个表项,则该表项失效,下次还要发送ARP请求来获得目的主机的MAC地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值