1,struct sockaddr 、struct sockaddr_in 和 struct in_addr
通用地址结构体(16字节)
struct sockaddr{
unsigned short sa_family;
char sa_date[14];
};
IPv4结构体(16字节)
struct sockaddr_in{
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8]; //占位,与通用结构体大小保持一致
};
struct in_addr{
unsigned int s_addr; //无符号32位网络地址
};
以前总是混淆这几个结构体在网络编程中的使用,就目前的理解来看:
- sockaddr_in用于编写sock代码时,方便我们对地址结构的赋值,所以在编写应用层代码时候,地址结构的初始化使用该结构体。
- sockaddr -->通用的地址结构,目前主要使用得到的地方在accept、connect函数中,这几个API使用的我们 初始化的地址结构时,需要强制转换为struct sockaddr *,为了方便理解,相当于sockaddr用于内核识别地址结构,sockaddr_in用于我们在应用层的代码编程。
- in_addr : 其结构体中只有一个变量,用于存储数值类型的ip地址,一般会在地址转换函数中使用到。
sin_port和sin_addr都必须是网络字节序(NBO)
程序员不应操作sockaddr,sockaddr是给操作系统用的
程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口,使用更方便。
in_addr 在地址函数转换调用时使用
2、网络编程中频繁使用的函数简单总结
int socket(int domain, int type, int protocol)
domain:域,
可以理解为是网络中的(AF_INIT | PF_INIT),
还是操作系统中的 (AF_UNIX |PF_UNIX == AF_LOCAL/PF_LOCAL)
type:
SOCK_STREAM | SOCK_DGRAM
return :
-1 ERROR
//绑定套接字与网络地址
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
参数:
sockfd:待连接套接字
addr:包含本地地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小
return : -1 ERROR 0 SUCCESS
/*
刚刚讲的sockaddr 结构是这个函数的参数,所以当我们使用sockaddr_in时,调用bind函数就需要进行地
址转换
*/
//监听套接字
listen(int sockfd , int backlog)
backlog:最大同时接收连接请求个数
return :
成功:0,并将 sockfd 设置为监听套接字
失败:-1
//等待对端连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
sockfd:监听套接字
addr:通用地址结构体,用以存储对端地址(IP+PORT)
addrlen:参数 addr 的存储区域大小
return:
成功:已连接套接字(非负整数)
失败:-1
/*
该等待地址链接函数:也使用的通用地址结构
*/
地址转换函数的使用:
inet_aton( )
#include <arpa/inet.h>
将strptr所指的字符串转换成32位的网络字节序二进制值
int inet_aton(const char *strptr, struct in_addr *addrptr);
inet_ntoa( )
将32位网络字节序二进制地址转换成点分十进制的字符串。
char *inet_ntoa(stuct in_addr inaddr);
inet_pton()
将IPV4/IPV6的地址转换成binary格式
int inet_pton(int af, const char *src, void *dst);
inet_ntop()
将二进制地址转化为文本地址
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
//在编程时需要地址转来转去,一般使用下面的函数
inet_addr( )
功能同上,返回转换后的地址。
int_addr_t inet_addr(const char *strptr);
代码测试:
#include <stdio.h>
#include <stdlib.h>
//函数引用头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
char mySip[16]="192.168.100.36";
unsigned int myNip=0xC0A86424;
//inet_addr
unsigned int swapIP = {0};
swapIP = inet_addr(mySip);
printf("inet_addr ip: %x\n", swapIP);
//inet_aton()
struct in_addr serIP = {0};
inet_aton( mySip, (struct in_addr *)&serIP);
printf("inet_aton ip: %x\n", serIP.s_addr);
//inet_ntoa()
char *pIp =NULL;
pIp = inet_ntoa( serIP );
printf("inet_ntoa ip: %s\n", pIp);
//inet_pton()
unsigned int pnIP = 0;
if(0 == inet_pton( AF_INET, "192.168.100.36", (void *)&pnIP))
{
printf("inet_pton Some Error\n");
}else
printf("inet_pton ip: %x\n" , pnIP);
//inet_ntop()
char buf[20]={0};
if(NULL == inet_ntop( AF_INET, (void *)&pnIP, buf, 20))
{
printf("inet_ntop Some Error\n");
}else
printf("inet_ntop ip: %s\n" , buf);
return 0;
}
结果:
[root@hero work]# ./a.out
inet_addr ip: 2464a8c0
inet_aton ip: 2464a8c0
inet_ntoa ip: 192.168.100.36
inet_pton ip: 2464a8c0
inet_ntop ip: 192.168.100.36