企业门户网站静态模板办公室装修注意事项
web/
2025/10/5 18:36:53/
文章来源:
企业门户网站静态模板,办公室装修注意事项,做虾皮网站,利用赞赏码做网站收款此为牛客Linux C课程和黑马Linux系统编程笔记。
1. 网络字节序
我们已经知道#xff0c;内存中的多字节数据相对于内存地址有大端和小端之分。 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分#xff0c;那么如何定义网络数…此为牛客Linux C课程和黑马Linux系统编程笔记。
1. 网络字节序
我们已经知道内存中的多字节数据相对于内存地址有大端和小端之分。 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分那么如何定义网络数据流的地址呢发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出接收主机把从网络上接到的字节依次保存在接收缓冲区中也是按内存地址从低到高的顺序保存因此网络数据流的地址应这样规定先发出的数据是低地址后发出的数据是高地址。
TCP/IP协议规定网络数据流应采用大端字节序即低地址高字节。例如发送主机中地址0-1存储16位的源端口号这个端口号是10000x3e8则地址0是0x03地址1是0xe8也就是先发0x03再发0xe8这16位在发送主机的缓冲区中也应该是低地址存0x03高地址存0xe8。但是如果发送主机是小端字节序的则地址0存储0xe8地址1存储0x03接收方接收到的端口号就成了593950xe803而不是1000。因此发送主机把1000填到发送缓冲区之前需要做字节序的转换。同样地接收主机如果是小端字节序的接到16位的源端口号也要做字节序的转换。如果主机是大端字节序的发送和接收都不需要做转换。同理32位的IP地址也要考虑网络字节序和主机字节序的问题。
为使网络程序具有可移植性使同样的C代码在大端和小端计算机上编译后都能正常运行可以调用以下库函数做网络字节序和主机字节序的转换。
#include arpa/inet.h
uint32_t htonl(uint32_t hostlong); // 32位host转为net用于主机向网络发送IP时的转换
uint16_t htons(uint16_t hostshort); // 16位host转为net用于主机向网络发送IP时的转换
uint32_t ntohl(uint32_t netlong); // 32位net转为host用于主机向网络发送端口号时的转换
uint16_t ntohs(uint16_t netshort); // 16位net转为host用于主机向网络发送端口号时的转换h表示hostn表示networkl表示32位长整数IP地址为32位s表示16位短整数端口号位16位。
如果主机是小端字节序这些函数将参数做相应的大小端转换然后返回如果主机是大端字节序这些函数不做转换将参数原封不动地返回。
2. IP地址转换函数
通常人们习惯用可读性好的字符串来表示 IP 地址比如用点分十进制字符串表示 IPv4 地址以及用 十六进制字符串表示 IPv6 地址。但编程中我们需要先把它们转化为整数二进制数方能使用。而记录 日志时则相反我们要把整数表示的 IP 地址转化为可读的字符串。
#include arpa/inet.h
// p:点分十进制的IP字符串n:表示network网络字节序的整数
int inet_pton(int af, const char *src, void *dst);af:地址族 AF_INET表示ipv4 AF_INET6表示ipv6 src:需要转换的点分十进制的IP字符串 dst:转换后的结果保存在这个里面
#include arpa/inet.h
// 将网络字节序的整数转换成点分十进制的IP地址字符串
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);af:地址族 AF_INET表示ipv4 AF_INET6表示ipv6 src: 要转换的ip的整数的地址 dst: 转换成IP地址字符串保存的地方 size第三个参数的大小数组的大小 返回值返回转换后的数据的地址字符串和 dst 是一样的
3. socket 地址
socket 网络编程接口中表示 socket 地址的是结构体 sockaddr其定义如下
#include bits/socket.h
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
typedef unsigned short int sa_family_t;很多网络编程函数诞生早于 IPv4 协议那时候都使用的是 struct sockaddr 结构体为了向前兼容现在sockaddr 退化成了类似void *的作用传递一个地址给函数至于这个函数是 sockaddr_in 还是sockaddr_in6由地址族确定然后函数内部再强制类型转化为所需的地址类型
TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用的 socket 地址结构体它们分别用于 IPv4 和IPv6
#include netinet/in.h
struct sockaddr_in
{
sa_family_t sin_family; /* __SOCKADDR_COMMON(sin_) */
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of struct sockaddr. */
unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) - sizeof (struct in_addr)];
};
struct in_addr
{
in_addr_t s_addr;
};
struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))sin_family指定你所使用哪种协议ipv4或者ipv6. AF_INET : ipv4 AF_INET6 : ipv6 AF_UNIX, AF_LOCAL : 本地套接字通信进程间通信
sin_port 端口号
所有专用 socket 地址以及 sockaddr_storage类型的变量在实际使用时都需要转化为通用 socket 地址类型 sockaddr强制转化即可因为所有 socket 编程接口使用的地址参数类型都是 sockaddr。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/87508.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!