网络编程(字节序)

一、字节序的概念

字节序是指不同类型CPU主机,内存存储 多字节整数 序列的方式。

float, char, 字符串均没有字节序的说法

short, int , long , long long 有字节序的说法

小端字节序:低字节存储在低地址,高字节存储在高地址

大端字节序:低字节存储在高地址,高字节存储在低地址。

ps :

1. 取地址,获取的都是变量的首地址,即获取的是变量的最低的地址。

2. 内存中的数据读取,都是从低地址往高地址读取,读取完毕后经过大小端转换得到结果。

用共用体(联合体)的方式,判断本机的字节序?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
union
{
    unsigned int a;
    char b;
}s;
int main(int argc, const char *argv[])
{
    /*
       unsigned int a = 0x87654321;
       int* pa = &a;
       char b = 0;
       b = a;
       printf("%#x\n",*pa);
       printf("%#x\n",b);
       */
    /*
       unsigned int a =0x87654321;
       char *pa = (char*)&a;
       printf("%#x\n",*pa);
       if(0x21 == *pa)
       printf("这是一个小端字节序\n");
       else if(0x87 == *pa)
       printf("这是一个大端字节序\n");
       */
    s.a=0x87654321;
    printf("%#x\n",s.b);
    if(0x21 == s.b)
        printf("这是一个小端字节序\n");
    else if(0x87 == s.b)
        printf("这是一个大端字节序\n");

    return 0;
}
#include <stdio.h>

union t
{
    int a;
    char b;
};

int main(int argc, const char *argv[])
{
    unsigned int a = 0x87654321;
    char *pa = (char*)&a;

    if(0x21 == *pa)
        printf("这是一个小端\n");
    else if(0x87 == *pa)
        printf("这是一个大端\n");


    union t text;
    text.a = 1;                        
    if(1 == text.b)
        printf("这是一个小端\n");
    else if(0 == text.b)
        printf("这是一个大端\n");

    return 0;
}

 二、本地字节序与网络字节序

本地字节数:主机字节序(Host Byte Order) HBO

网络字节序(Network Byte Order) NBO,网络字节序规定使用大端字节序

在跨主机传输过程中,需要使用统一的字节序,即网络字节序,避免兼容性问题。

三、字节序转换函数

1)htons htonl 主机字节序-->网络字节序

头文件:

#include <arpa/inet.h>
​uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);

参数:指定要转换成网络字节序的整型:分别是32bit和16bit;

返回值:成功,返回转换后网络字节序的整型

#include <stdio.h>
#include <arpa/inet.h>
​
int main(int argc, const char *argv[])
{
    unsigned int a = 0x87654321;
    printf("%#x\n", a);             //0x87654321
    printf("%#x\n", htonl(a));      //0x21436587
​
    printf("%#x\n", htons(a));      //0x2143                 
    
    return 0;
}   

2)ntohs ntohl 网络字节序---->主机字节序

头文件:

#include <arpa/inet.h>

原型:

uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

参数:

uint32_t hostlong:32位网络字节序整型;
uint16_t hostshort:16位网络字节序整型;

返回值:成功,返回转换成主机字节序的整型;

四、结构体对齐

编译器会对结构体进行对齐,加速CPU取值周期,由于数据对齐也是与操作系统相关,不同的主机如果使用不同的对齐方式,会导致数据无法解析。

所以网络传输结构体的时候需要取消结构体对齐;

#include <stdio.h>
#pragma pack(1)         //设置默认对齐系数 :()中的参数只能填2^n (n=0,1,2,3,4,5......)  

typedef struct
{
    char a;     //1
    int b;      //4
    int d;      //4
}_A;
​
#pragma pack()      //重置默认对其系数,重新置为8
​
typedef struct
{
    char a;     //1
    int b;      //4
    int d;      //4
} __attribute__((packed))  B;       //取消结构体对齐
​
​
typedef struct
{   
    char a;     //1
                //3
    int b;      //4
    int d;      //4
}_C;
​
int main(int argc, const char *argv[])
{   
    printf("%ld\n", sizeof(_A));    //9
    printf("%ld\n", sizeof(_B));    //9
    printf("%ld\n", sizeof(_C));    //12
​
    
    return 0;
}

五、类型长度 

int long int不同操作系统这两个数据类型所占的字节数可能是不一样的

解决方式:可以通过通用类型:uint8_t uint16_t uint32_t

因为涉及到跨平台,不同平台会有不同的字长

#include <stdint.h>
​
typedef struct
{
    uint8_t a;      //1
    uint32_t b;      //4
    uint16_t d;      //2
}_A;

六、IP转换

由于IP地址本质上是一个4个字节的无符号整数,所以在跨主机传输中也有字节序的概念。

所以需要将IP地址转换成网络字节序。

"192.168.8.189" ---->本机字节序的整型 0xC0A808BD---->网络字节序0xBD08A8C0

"192.168.31.42"----> 0xC0A81F2A ---->0x2A1FA8C0

6.1点分十进制--->网络字节序

1)inet_aton

头文件:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

原型:

int inet_aton(const char *cp, struct in_addr *inp);

参数:

char *cp:源IP地址的点分十进制字符串,例如 “192.168.1.10”;
struct in_addr *inp:存储转换成网络字节序的IP;
           typedef uint32_t in_addr_t;
           struct in_addr {
               in_addr_t s_addr;
           };

返回值:

成功,返回非0;
失败,返回0;
​只能转换IPv4

例子:

 #define IP  "192.168.1.10"      //0xC0A8010A
 int main(int argc, const char *argv[])
 {
     struct in_addr inp;
 
     if(inet_aton(IP, &inp) == 0)
     {
         printf("转换失败\n");
         return -1;
     }
 
     printf("%#X\n", inp.s_addr);    //0X0A01A8C0
                                                           
     return 0;
 }            

2)inet_pton(既可以转IPv4也能处理IPv6)

头文件:

#include <arpa/inet.h>

原型:

  int inet_pton(int af, const char *src, void *dst);

参数:

int af:协议族
            AF_INET         IPV4
            AF_INET6        IPV6
char *src:指定要转换成网络字节序的点分十进制字符串;
     void* dst
           typedef uint32_t in_addr_t;
           struct in_addr {
               in_addr_t s_addr;
           };
​
            af == AF_INETa;
            struct in6_addr
            {
            }

返回值:

成功,返回1;
失败,返回0或者-1,更新errno;

2)inet_addr 最常用

头文件:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

原型:

uint32_t inet_addr(const char *cp);

参数:

char *cp:源IP地址的点分十进制字符串,例如 “192.168.1.10”;

返回值:

成功,返回转换后的网络字节序IP地址;
typedef uint32_t in_addr_t;
​失败,返回INADDR_NONE (usually -1);

6.2网络字节序--->点分十进制

1)inet_ntoa 常用

头文件:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

原型:

char *inet_ntoa(struct in_addr in);

参数:

struct in_addr in:指定要转换成点分十进制字符串的IP地址;
           typedef uint32_t in_addr_t;
           struct in_addr {
               in_addr_t s_addr;
           };

返回值:

成功,返回点分十进制字符串的首地址;

2)inet_ntop

头文件:

#include <arpa/inet.h>

原型:

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

参数:

 int af:协议族
            AF_INET         IPV4
            AF_INET6        IPV6
 void* src:存储要转换成点分十进制字符串的IP首地址;
           typedef uint32_t in_addr_t;
           struct in_addr {
               in_addr_t s_addr;
           };
​
            af == AF_INETa;
            struct in6_addr
            {
            }
 char *dst:存储转换后的结果,点分十进制的首地址;
 socklen_t size:缓冲区大小,其实就是指定多大的空间用于转换IP;

返回值:

成功,返回字符串的首地址,就是dst;
失败,返回NULL,更新errno;   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/81884.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

常见架构类型

目录 1.单机架构 2.应用数据分离架构 3.读写分离架构 4.冷热分离架构 5.垂直分库架构 6.微服务架构 7.容器编排架构 1.单机架构 单机架构是简单的将应用服务和数据库服务部署到同一台机器上。 缺点&#xff1a;存在很大的性能限制。 2.应用数据分离架构 引入负载均衡&a…

vue3+elementPlus table里添加输入框并提交校验

<template><div><el-form :model"info" ref"forms"><el-tableref"tableRef":data"info.data"border><el-table-column align"center" property"name" label"*姓名"><…

mapper.xml中循环执行多条语句时报错,但是单独拿SQL到数据库却可以执行

我是批量修改数据&#xff0c;用foreach标签包住update语句&#xff0c;报错信息如下&#xff1a; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the …

Dubbo 融合 Nacos 成为注册中心

快速上手 Dubbo 融合 Nacos 成为注册中心的操作步骤非常简单&#xff0c;大致步骤可分为“增加 Maven 依赖”以及“配置注册中心“。 增加 Maven 依赖 只需要依赖Dubbo客户端即可&#xff0c;关于推荐的使用版本&#xff0c;请参考Dubbo官方文档或者咨询Dubbo开发人员&#…

vite打包遇到的错误

1.js emit is not supported 2.将package.json中的bulid后面写成“vue-tsc --noEmit --skipLibCheck && vite build” 3.再次打包成功

微信程序 自定义遮罩层遮不住底部tabbar解决

一、先上效果 二 方法 1、自定义底部tabbar 实现&#xff1a; https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 官网去抄 简单写下&#xff1a;在代码根目录下添加入口文件 除了js 文件的list 需要调整 其他原封不动 代码&#xf…

RT1052的EPWM

文章目录 1 EPWM介绍1.1 引脚1.2 时钟1.3 比较寄存器 2 函数 1 EPWM介绍 RT1052 具有 4 个 eFlexPWM(eFlexWM1~eFlex_PWM4)。 每个 eFlexPWM 可以产生四路互补 PWM即产生 8 个 PWM&#xff0c;也可以产生相互独立的 PWM 波。四路分别是模块0-3每个 eFlexPWM 具有各自的故障检…

opencv进阶09-视频处理cv2.VideoCapture示例(打开本机电脑摄像头)

视频信号&#xff08;以下简称为视频&#xff09;是非常重要的视觉信息来源&#xff0c;它是视觉处理过程中经常要处理的一类信号。实际上&#xff0c;视频是由一系列图像构成的&#xff0c;这一系列图像被称为帧&#xff0c;帧是以固定的时间间隔从视频中获取的。获取&#xf…

react之路由的安装与使用

一、路由安装 路由官网2021.11月初&#xff0c;react-router 更新到 v6 版本。使用最广泛的 v5 版本的使用 npm i react-router-dom5.3.0二、路由使用 2.1 路由的简单使用 第一步 在根目录下 创建 views 文件夹 ,用于放置路由页面 films.js示例代码 export default functio…

如何在前端实现WebSocket发送和接收UDP消息(多线程模式)

目录 简介&#xff1a;步骤1&#xff1a;创建WebSocket连接步骤2&#xff1a;创建Web Workers步骤3&#xff1a;发送和接收UDP消息&#xff08;多线程模式&#xff09;结束语&#xff1a; 简介&#xff1a; 本文将继续介绍如何在前端应用中利用WebSocket技术发送和接收UDP消息…

C#生产流程控制(串行,并行混合执行)

开源框架CsGo https://gitee.com/hamasm/CsGo?_fromgitee_search 文档资料&#xff1a; https://blog.csdn.net/aa2528877987/article/details/132139337 实现效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37…

vue 关闭prettier警告warn

这个就是我们创建vue cli的时候 把这个给默认上了 关闭这个只需在.eslintrc.js页面里边添加一行代码"prettier/prettier": "off"

从零开始创建 Spring Cloud 分布式项目,不会你打我

目录 一、Spring Cloud 和 分布式 二、创建新项目 三、导入 Spring Cloud 依赖 四、配置 Spring Cloud 一、Spring Cloud 和 分布式 Spring Cloud是一个基于Spring框架的开源微服务框架&#xff0c;它提供了一系列工具和组件&#xff0c;用于帮助开发人员构建分布式系统中…

(学习笔记-进程管理)什么是悲观锁、乐观锁?

互斥锁与自旋锁 最底层的两种就是 [互斥锁和自旋锁]&#xff0c;有很多高级的锁都是基于它们实现的。可以认为它们是各种锁的地基&#xff0c;所以我们必须清楚它们之间的区别和应用。 加锁的目的就是保证共享资源在任意时间内&#xff0c;只有一个线程访问&#xff0c;这样就…

韦东山老师 RTOS 入门课程(一)RTOS 介绍,熟悉裸机的汇编逻辑

韦东山老师 RTOS 入门课程 课程链接&#xff1a;韦东山直播公开课&#xff1a;RTOS实战项目之实现多任务系统 第1节&#xff1a;裸机程序框架和缺陷_哔哩哔哩_bilibili RTOS 介绍 裸机&#xff1a;固定顺序执行。 中断&#xff1a;可以一直专心做循环里的事情&#xff0c;直…

最长回文子串

给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 示例 1&#xff1a; 输入&#xff1a;s “babad” 输出&#xff1a;“bab” 解释&#xff1a;“aba” 同样是符合题意的答案。 示例 2&#xff1a; 输入&#xff1a;s “cbbd” 输出&#xff1a;“bb” 提示&#xff…

排序算法-冒泡排序(C语言实现)

简介&#x1f600; 冒泡排序是一种简单但效率较低的排序算法。它重复地扫描待排序元素列表&#xff0c;比较相邻的两个元素&#xff0c;并将顺序错误的元素交换位置&#xff0c;直到整个列表排序完成。 实现&#x1f9d0; 以下内容为本人原创&#xff0c;经过自己整理得出&am…

SQL-Injection

文章目录 引入columns表tables表schemata表以sqli-labs靶场为例路径获取常见方法文件读取函数文件写入函数防注入 数字型注入(post)字符型注入(get)搜索型注入xx型注入 引入 在MYSQL5.0以上版本中&#xff0c;mysql存在一个自带数据库名为information_schema,它是一个存储记录…

C++之模板进阶

模板进阶 非类型模板参数模板的特化概念函数模板特化类模板特化全特化偏特化 模板分离编译什么是分离编译模板的分离编译解决方法 模板总结 非类型模板参数 模板参数分两种&#xff1a;类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class…

华为OD机试关于无输入截止条件的ACM输入逻辑

无输入截止条件的ACM输入 华为OD机试题中有一些题目是没有输入截止条件的,比如 华为OD机试 - 数字游戏(Java & JS & Python)_伏城之外的博客-CSDN博客 从输入描述来看,每组有两行输入,但是并没有告诉我们具体有几组? 那么输入该如何截止呢? 此时,有两种输入…