网络编程——字节序和地址转换

字节序和地址转换

一、字节序

1、字节序概念

是指多字节数据的存储顺序,数据在内存中存储的方式

2、分类

大端序(网络字节序):高位的数据存放在低地址位 arm架构、交换机、路由器
小端序(主机字节序):高位的数据存放在高地址位 x86架构计算机
注意
LSB : 低地址
MSB: 高地址
在这里插入图片描述

3、字节序转换

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

①host -->to–>network

//将32位主机字节序数据转换成网络字节序数据
uint32_t htonl(uint32_t hostlong);//l代表长整型
//将16位主机字节序数据转换成网络字节序数据
uint16_t htons(uint16_t hostshort);//s代表短整型

主机字节序转换为网络字节序:htons(6666); //将端口号6666转换为网络字节序
网络字节序转换为主机字节序:ntohs(6666); //将端口号6666转换为主机字节序

二、地址转换

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

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

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

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

in_addr_t inet_addr(const char *cp);

1、inet_pton

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

功能:将32位的无符号整形数据转化为点分十进制的IP地址
返回值:如果转换成功,返回 1;如果提供的IP地址格式无效,返回 0;如果发生错误,返回 -1。
参数说明:
af:地址族(Address Family),可以是 AF_INET(IPv4)或 AF_INET6(IPv6)。
src:待转换的字符串格式的IP地址。
dst:用于存储转换后的二进制格式IP地址的缓冲区。

示例:将IP地址字符串转为整数的IP

#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{ 
    char IP[] = "192.168.16.209";
    int ip_int = 0;
    unsigned char *p = NULL;//一定是无符号
    p = (char *)&ip_int;  
    int ret = inet_pton(AF_INET, IP, &ip_int);
    if (ret < 0) {
        perror("inet_pton");
        exit(-1);
    }
    printf("%d.%d.%d.%d\n", *p, *(p + 1), *(p + 2), *(p + 3));
    return 0;

    return 0;
} 

2、inet_ntop(将32位的无符号整型数据转为点分十进制的IP地址)

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

功能:将点分十进制的IP地址转化为32位的无符号
返回值:如果转换成功,返回指向 dst 的地址;如果提供的IP地址族无效,返回 NULL。
参数说明:
af:地址族(Address Family),可以是 AF_INET(IPv4)或 AF_INET6(IPv6)。
src:待转换的二进制格式的IP地址。
dst:用于存储转换后的字符串格式IP地址的缓冲区。
size:dst 缓冲区的大小。
案例

#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{ 
    unsigned char ip_int[] = {192,168,16,209};
    char ip_str[16] = "";
    inet_ntop(AF_INET, &ip_int, ip_str, sizeof(ip_str));
    printf("%s\n", ip_str);

    return 0;
} 

3、inet_addr、inet_ntoa

只能用于IPV4的地址转换

in_addr_t inet_addr(const char cp);

功能:将整形数据的IP地址转化为点分十进制IP地址
返回值:如果转换成功,返回转换后的二进制格式IP地址;如果提供的IP地址格式无效,返回 INADDR_NONE(通常为 -1)。
参数说明:
cp:待转换的字符串格式的IP地址。

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

功能:将整形数据转换化为点分十进制的IP地址
返回值:如果转换成功,返回非零值;如果提供的IP地址格式无效,返回 0。
参数说明:
cp:待转换的字符串格式的IP地址。
inp:用于存储转换后的二进制格式IP地址的结构体。

struct sockaddr_in {
	sa_family_t sin_family; /* 地址族: AF_INET */
    u_int16_t sin_port; /* 按网络字节次序的端口 */
    struct in_addr sin_addr; /* internet地址 */
};

 /* Internet地址. */
struct in_addr {
	u_int32_t s_addr; /* 按网络字节次序的地址 */
};
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{ 
	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = 8080;
	saddr.sin_addr.s_addr = inet_addr("192.168.16.209");
	printf("ip:%s port:%d\n", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在 Linux 内核编程中,经常需要处理网络数据,因此需要进行网络字节转换网络字节是指在网络上传输数据时使用的字节,它与主机字节(本地字节)不同。 在 x86 架构的计算机中,主机字节是小端(即低位字节存储在内存的低地址处),而网络字节是大端(即高位字节存储在内存的低地址处)。因此,在进行网络数据传输时,需要进行字节转换。 Linux 内核提供了一些函数用于进行字节转换,如: - htons() 和 ntohs() 函数用于将 16 位整数在主机字节网络字节之间转换。 - htonl() 和 ntohl() 函数用于将 32 位整数在主机字节网络字节之间转换。 这些函数都定义在头文件 <arpa/inet.h> 中。例如,将一个 16 位整数从主机字节转换网络字节,可以使用以下代码: ```c #include <arpa/inet.h> uint16_t host_number = 12345; uint16_t network_number = htons(host_number); ``` 同样地,将一个 32 位整数从主机字节转换网络字节,可以使用以下代码: ```c #include <arpa/inet.h> uint32_t host_number = 123456789; uint32_t network_number = htonl(host_number); ``` 反之,将一个从网络中接收到的数据从网络字节转换为主机字节,可以使用以下代码: ```c #include <arpa/inet.h> uint16_t network_number = 0x1234; uint16_t host_number = ntohs(network_number); ``` ```c #include <arpa/inet.h> uint32_t network_number = 0x12345678; uint32_t host_number = ntohl(network_number); ``` 需要注意的是,在进行字节转换时,必须使用适当的数据类型(如 uint16_t 和 uint32_t),否则可能会出现意外的错误。 ### 回答2: 在Linux内核编程中,网络字节转换是一个常见的操作,因为网络传输中使用的是大端字节(也称为网络字节),而计算机内部一般使用的是小端字节。 在进行网络通信时,需要将数据从主机字节转换网络字节,以确保数据的正确传输和解析。同样,在接收到网络数据后,也需要将数据从网络字节转换为主机字节,以便正确地处理和使用这些数据。 在Linux内核中,提供了一系列的函数来进行字节转换。其中,主要使用的函数为`htonl()`、`htons()`、`ntohl()`和`ntohs()`。它们分别代表主机到网络长整型、主机到网络短整型、网络到主机长整型和网络到主机短整型的转换。 这些函数的命名规则是根据网络字节的缩写和数据类型的缩写组合而成的。其中,h代表主机字节(host),n代表网络字节(network),l代表长整型(long),s代表短整型(short)。 使用这些函数进行字节转换非常简单。例如,要将一个32位整型数从主机字节转换网络字节,可以使用`htonl()`函数,如下所示: ``` uint32_t value = 12345678; uint32_t network_value = htonl(value); ``` 同样地,要将一个网络字节的32位整型数转换为主机字节,可以使用`ntohl()`函数,如下所示: ``` uint32_t network_value = 0x1020304; uint32_t host_value = ntohl(network_value); ``` 总之,在Linux内核编程中,网络字节转换是非常常见的操作,可以使用`htonl()`、`htons()`、`ntohl()`和`ntohs()`这些函数来实现。这些函数提供了方便、简单和可靠的方式来进行字节转换,以确保网络数据的正确传输和处理。 ### 回答3: 在Linux内核编程中,网络字节转换是一个非常重要的概念。网络字节,也被称为大端字节,是一种统一的字节,用于在网络中传输数据。而在计算机内部,一般使用的是主机字节,也就是与处理器相关的字节。为了在不同主机之间进行网络通信,就需要进行字节转换。 Linux内核提供了一系列函数用于进行字节转换,这些函数主要集中在`linux/in.h`和`linux/tcp.h`头文件中。其中最常用的函数是`htonl`、`htons`、`ntohl`和`ntohs`。它们分别用于将主机字节转换网络字节和将网络字节转换为主机字节。 这些函数的原理是通过位操作和移位运算来实现字节转换。例如,`htonl`函数可以将32位的整数从主机字节转换网络字节,它将高位字节和低位字节进行位置交换。而`ntohl`函数则在将网络字节转换为主机字节时,执行与之相反的操作。 在实际的内核编程中,我们需要根据具体情况选择合适的字节转换函数。比如,在编写网络设备驱动程时,需要将设备收到的网络数据转换为主机字节进行处理,这时就可以使用`ntohl`和`ntohs`函数。而在将数据发送到网络上时,则需要将主机字节转换网络字节,这时可以使用`htonl`和`htons`函数。 总而言之,通过Linux内核提供的网络字节转换函数,我们可以方便地进行主机字节网络字节之间的转换,从而实现跨主机的网络通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值