zoukankan      html  css  js  c++  java
  • Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)

    IPv4套接字地址结构
    struct sockaddr_in
    {
        uint8_t sinlen;(4个字节)
        sa_family_t sin_family;(4个字节)
        in_port_t sin_port;(2个字节)
        struct in_addr sin_addr;(4个字节)
        char sin_zero[8];
    };
    sin_len:整个sockaddr_in结构体的长度,部分Linux内核版本没有该成员
    sin_family:指定该地址家族,一般设置为AF_INET(使用TCP,UDP协议)
    sin_port:端口
    sin_addr:IPv4的地址
    sin_zero:暂不使用,一般将其设置为0
    
    通用地址结构
    struct sockaddr
    {
        uint8_t sin_len;(4个字节)
        sa_family_t sin_family;(4个字节)
        char sa_data[14];
    };
    sin_len:整个sockaddr结构的长度
    sin_family:指定该地址家族
    sa_data:由sin_family决定它的形式
    
    结论:struct sockaddr_in与struct sockaddr结构大小相同
    字节序
    大端字节序
    --最高有效位存储与最低内存地址处,最低有效位存储于最高内存地址处
    
    小端字节序
    --最高有效位存储于最高内存地址处,最低有效位存储于最低内存地址处
    
    主机字节序
    --不同主机有不同的字节序,如x86小端字节序,,Motorola 6800为大端字节序
    
    网络字节序
    --网络字节序规定为大端字节序
    
    字节序说明:一个int类型变量254存储在内存中,如果变量的百位存储于内存地址条上的低地址处,
    个位存储于内存地址条上的高地址处(即变量存储序列和内存地址序列相反)这就是大端字节序,反之则是小端字节序。
    各个主机的字节序是不同的,但是在网络中传输,必须要一个统一的字节序,这就是网络字节序。
    字节序转换函数
    uint32_t htonl(uint32_t hostlong);
    uint16_t htons(uint16_t hostshort);
    uint32_t ntohl(uint32_t netlong);
    uint16_t ntohs(uint16_t netshort);
    说明:在上述函数中,h代表host;n代表networks;s代表short;l代表long。
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    
    int main(int arg, char *args[])
    {
        unsigned int data = 0x12345678;
        char *p = (char *)&data;
        printf("%x,%x,%x,%x
    ", p[0], p[1], p[2], p[3]);
        /*
         * 对于数组而言,内存地址一定是递增的,p[0]=*(p+0);p[1]=*(p+1);
         * 如果data变量的最低有效位处于p+0这个低内存地址位,说明这是小端字节序
         * */
        if (p[0] == 0x78)
        {
            printf("主机是小端字节序
    ");
        } else
        {
            printf("主机是大端字节序
    ");
        }
        //字节序转换函数
        uint32_t ndata = htonl(data);
        p = (char *)&ndata;
        printf("%x,%x,%x,%x
    ", p[0], p[1], p[2], p[3]);
        if (p[0] == 0x78)
        {
            printf("网络字节序是小端字节序
    ");
        } else
        {
            printf("网络字节序是大端字节序
    ");
        }
        return 0;
    }
    地址转换函数
    typedef uint32_t in_addr_t;
    struct in_addr {
        in_addr_t s_addr;
    };
    
    int inet_aton(const char *p,struct in_addr *inp);
    将点分十进制(192.168.1.116)转化成struct in_addr
    
    in_addr_t inet_addr(const char * cp);
    将点分十进制转化成32bit
    
    char *inet_ntoa(struct in_addr in);//注意:这里参数是结构体变量,而非结构体指针
    将struct结构体变量转化成点分十进制
    inet_ntoa()返回值是char *,这个char *的内存空间是在inet_ntoa()函数中静态分配的,因此inet_ntoa()后面的调用会覆盖上一次调用,inet_ntoa()是线程不安全函数
    套接字类型
    1.流式套接字(SOCK_STREAM)
    --提供面向连接的,可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收。
    2.数据报式套接字(SOCK_DGRAM)
    --提供无连接服务,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
    3.原始套接字(SOCK_RAW)
  • 相关阅读:
    Socket Client & Server
    2台整机,多线程运行测试时间不稳定
    去了一趟宝马铁西工厂,才知道工厂已经在数字孪生
    窗帘电机测试系统调试心得
    AntDesignBlazor 学习笔记
    简单粗暴的实现 Blazor Server 登录鉴权
    Blazor 子组件与父组件通过 ChildEvents 传递数据的方法
    EasyExcel 列 固定下拉选项的做法
    Java代码在数据库存取某些敏感字段的加解密做法
    nacos 使用【一】 创建一个属于自己的配置空间
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6114193.html
Copyright © 2011-2022 走看看