zoukankan      html  css  js  c++  java
  • TCP/IP协议栈 --- 网络层(IP 首部 和分片)

    IP 是TCP/IP协议栈中重要的层次, TCP UDP ICMP IGMP都是依赖IP层进行传输的。首先它是一种不可靠,无连接的协议。不可靠:它不保证IP包能正确到达目的地,无连接:表示IP并不会维护后续数据包的信息,每个数据包的传输都是独立的。数据包的可靠性需要依赖传输层协议来保证如TCP协议,也就是说当一个比特流从网络接口发送向网络之后,所经过的每个路由器会解析数据包的网络层的信息,再通过路由算法选一条路发送出去,所有包不一定会选择同一条道路。网络层负责点到点的通信,尽量将数据包发送到目的主机,若不能到达目的主机IP有一个简单的错误处理算法:丢弃该数据报,然后发送 ICMP消息报给信源端。
    

    IP首部信息:

    这里写图片描述

    如果没有IP选项的话IP首部应该是20字节。用wireshark抓包分析一下
    这里写图片描述

    4位版本号: 0100 表示IPv4 若是IPv6的话应该是0110
    4位首部长度:0101 表示20个字节,这是因为首部长度指的是首部占 32 bit字的数目,包括任何选项。由于它是一个 4比特字段,因此首部最长为6 0个字节。也就是说这四个比特一个比特表示4个字节。
    8位服务类型:服务类型(TO S)字段包括一个3 bit的优先权子字段(现在已被忽略) ,4 bit的TOS子字段和1 bit未用位但必须置0。4 bit的TOS分别代表:最小时延、最大吞吐量、最高可靠性和最小费用。普通数据包里一般都为0x00. 对于不同应用可能会选择不同的TOS。如TFTP telnet等。
    16位总长度:表明IP数据包的总长度 最大65535个字节, 但考虑到链路层的MTU 一般这个值要小于1500。拿这个总长度减去IP首部长度就是TCP UDP 等数据包长度。
    接下来的4个字节就是表示IP分片的记录信息:
    这里写图片描述
    前两个字节表示:那个数据包的分片,标识同一个数据报分片
    3位标志表示:是否有更多分片,最后一个IP分片里都为0表示没有分片了
    13位片偏移:分片在原始数据的偏移量。
    另外在分片过程中传输层信息只会出现在第一个分片中。IP层不知道也不需要保证在每个分片中都有传输层首部。到达目的主机时IP层会把这些IP片组合起来。若有片丢失的话,就会重传整个数据报。组合起来的数据报再交给传输层解析。
    这里写图片描述

    最后的几个字节包含目的IP源IP和IP选项(若有)。
    下面做一个UDP传输实例看一下IP层分片。

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define PORT 4444
    int main(int argc, char *argv[])
    {
        if(argc != 2)
        {
            printf("./udpclient IP
    ");
            return 1;
        }
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0)
            return 1;
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(PORT);
        if (!inet_pton(AF_INET, argv[1], (void *)&server.sin_addr))
        {
            printf("IP error
    ");
            return -1;
        }
        char buff1[65535] = "sdfsdfsdf";
        char buff2[2048] = {0};
        socklen_t size = sizeof(struct sockaddr);
        while(1)
        {
            sendto(fd, buff1, 65535, 0, (const struct sockaddr *)&server, size);
            sleep(5);
            recvfrom(fd, buff2, 2048, 0, NULL, NULL);
            printf("recv : %s
    ", buff2);
        }
    
    }

    服务器端

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define PORT 4444
    int main()
    {
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if(fd < 0)
            return -1;
        struct sockaddr_in server, client;
        server.sin_family = AF_INET;
        server.sin_port = htons(PORT);
        server.sin_addr.s_addr = htonl(INADDR_ANY);
        bind(fd, (const struct sockaddr *)&server, sizeof(struct sockaddr));
        socklen_t len  = sizeof(struct sockaddr);
        char buff[2048] = {0};
        while(1)
        {
            recvfrom(fd, buff, 2048, 0,(struct sockaddr *)&client, &len);
            printf("%s send msg: %s 
    ", inet_ntoa(client.sin_addr), buff);
            sendto(fd, "OK", 2, 0, (const struct sockaddr *)&client, len);
        }
    }

    抓包结果可以看到:

    ~# tcpdump -i eth0 -v udp and host 192.168.1.3
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    18:21:40.171370 IP (tos 0x0, ttl 64, id 39920, offset 0, flags [+], proto UDP (17), length 1500)
        192.168.1.3.39170 > 192.168.1.4.4444: UDP, length 2048
    18:21:40.171385 IP (tos 0x0, ttl 64, id 39920, offset 1480, flags [none], proto UDP (17), length 596)

    这里可以看到被分成的两个组,2096 - 2048 = 48字节: 多出的48个字节包含俩个IP头40 + 一个UDP头8 字节??

  • 相关阅读:
    January 25th, 2018 Week 04th Thursday
    January 24th, 2018 Week 04th Wednesday
    January 23rd, 2018 Week 04th Tuesday
    January 22nd, 2018 Week 04th Monday
    January 21st, 2018 Week 3rd Sunday
    January 20th, 2018 Week 3rd Saturday
    January 19th, 2018 Week 3rd Friday
    January 18th, 2018 Week 03rd Thursday
    January 17th, 2018 Week 03rd Wednesday
    January 16th, 2018 Week 03rd Tuesday
  • 原文地址:https://www.cnblogs.com/MaAce/p/7755702.html
Copyright © 2011-2022 走看看