linux网络编程 -- 转化函数

套接字(socket):地址+端口
是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。

1、socket的信息数据结构

  • sockaddr
struct sockaddr {
	//地址族 AF_INET表示ipv4  AF_INET6表示ipv6
	sa_family_t sa_family;
	 
	//14字节的协议地址,包含该socket的ip地址和端口号
	char        sa_data[14];
}
  • sockaddr_in
    是sockaddr的改进版
struct sockaddr_in {
	//地址族
	short int sin_family; 

	//端口号
	unsigned short int sin_port;

	//ip地址
	struct in_addr sin_addr;

	//填充0以保持和struct sockaddr大小一样          
	unsigned char sin_zero[8];        
};
  • in_addr
struct in_addr{
	//32位ipv4地址,网络字节序
	unsigned long int s_addr;
};

2、ipv4地址与二进制数字的转化

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef uint32_t in_addr_t;
//将ipv4地址转成二进制数字,失败返回-1
in_addr_t inet_addr(const char *cp);

//将ipv4地址转成二进制数字,把结果放在inp所指的内存中,失败返回0
int inet_aton(const char *cp, struct in_addr *inp);
//将二进制数字转成将ipv4地址,返回指向结果的指针
char *inet_ntoa(struct in_addr in);


//将二进制数字转换为ipv4或ipv6 ip地址。
const char *inet_ntop(int af, const void *src,
                             char *dst, socklen_t size);
//将ipv4或ipv6 ip地址转换为数字二进制形式
int inet_pton(int af, const char *src, void *dst);                             

3、网络字节序与主机字节序的转化

  • 小端模式:低地址存放低字节
  • 大端模式:低地址存放高字节
  • 主机字节序有可能是大端或小端,网络字节序都是大端模式
#include <arpa/inet.h>
//将 32/16 位的主机字节序转化为网络字节序并返回
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);

//将 32/16 位的网络字节序转化为主机字节序并返回
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

uint32_t 相当于 unsigned long int
uint16_t 相当于 unsigned short int
h 代表 host 、n 代表 network
s 代表 short、l 代表 long

4、验证

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

void check(){
    int i = 0x12345678;

    char *p = (char *)&i;

    if (*p == 0x12)
        printf("主机为大端模式\n");
    else
        printf("主机为小端模式\n");
}

int main() {
    char *ip = "192.168.200.100";
    struct in_addr inp;
    struct in_addr num;

    inet_aton(ip,&inp);//地址转数字
    num.s_addr  = inet_addr(ip);//地址转数字

    check();//判断主机大小端
    printf("地址转数字(inet_aton): %x\n",  inp.s_addr);
    printf("地址转数字(inet_addr): %x\n",  num.s_addr);
    printf("网络转主机(ntohl): %x\n", ntohl( num.s_addr));
    printf("主机转网络(htonl): %x\n", htonl( num.s_addr));

    printf("数字转地址: %s\n", inet_ntoa(num));

}

11000000.10101000.11001000.01100100
c0.a8.c8.64
192.168.200.100

在这里插入图片描述
猜测ntohl和htonl都只是将大小端互换

5、主机名与地址转化

#include <netdb.h>
#include <sys/socket.h>  
struct hostent *gethostbyname(const char *name);//将主机名转换为ip地址
struct hostent *gethostbyaddr(const void *addr,
                                     socklen_t len, int type);

struct hostent {
    char  *h_name;            /* 正式主机命 */
    char **h_aliases;         /* a主机别名 */
    int    h_addrtype;        /* 主机ip地址类型 ipv4/ipv6 */
    int    h_length;          /* 主机ip地址长度 */
    char **h_addr_list;       /* 主机ip地址列表 */
}
#define h_addr h_addr_list[0] /* 保存ip地址 */

参考:man手册,《高质量嵌入式linuxc编程 第2版》349-354

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值