深入浅出IP地址
socket参数详解
- 函数原型:int socket(int domain, int type, int protocal);
参数 | 意义 |
---|
domain | 套接字中使用的协议簇信息 |
type | 套接字数据传输类型信息 |
protoool | 设备间通信使用的协议信息 |
参数 | 协议簇 |
---|
PF_INET | IPv4 |
PF_INT6 | IPv6 |
PF_LOCAL | 本地(进程间)通信 |
PF_PACKET | 底层数据收发 |
PF_IPX | Novell专用协议(互联网分组交换协议) |
- type参数:用于指定协议类型
– SOCK_STREAM : 流式数据(TCP)
– SOCK_UGRAM : 报文式数据(UDP) - protocol参数 : 用于指定协议簇中符合类型的具体协议
– domain和type几乎可以唯一确定一种协议,因此,这个参数通常为0;
– 即:0代表domain和type指定后的默认协议。 - Eg:socket(PF_INET,SOCK_STREAM,0);//代表使用基于IPv4的TCP协议
关于端口号和IP地址
- IP地址是一个4字节地址(可分为5类),端口号是一个2字节数据;
- 0~1023作为特定端口被预定义(分配给特定应用程序);
深入解析IP地址
- IP地址分为网路标识和主机标识两部分;
– 网路标识:标识网络主机所在的网络;
– 主机标识:标识网络主机的具体地址; - IP地址和子网掩码配合使用用于区分网络标识和主机标识;
- 子网掩码的表现形式也是一个4字节的整型数
- 子网掩码用于从IP地址中提取网络标识;
- 特殊地址:
– 0.0.0.0/0 :保留,常用于代表”缺省地址“;
– 127.0.0.0/8 : 回环地址,常用于本地软件回送测试;
– 255.255.255.255/32 :广播地址。 - 私有地址:不在公网使用,只在内网使用
– 10.0.0.0/8 ~10.255.255.255/8
– 172.16.0.0/16 ~ 172.31.255.255/16
– 192.168.0.0/24 ~ 192.168.255.255/24
网络编程中的地址类型
sock = socket(PF_INET,SOCK_STREAM,0);
if(sock == -1)
{
printf("socket error\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("47.99.217.175");
addr.sin_port = htons(80);
if(connect(sock,(struct sockaddr*)&addr,sizeof(addr)) == -1)
{
printf("connect error\n");
return -1;
}
len = send(sock,tosend,strlen(tosend),0);
printf("send bytes = %d\n",len);
len = recv(sock,buf,sizeof(buf),0);
printf("receive bytes = %d\n",len);
- AF_INET和PF_INET的区别: AF_INET代表的是IPv4地址(地址类型),PF_INET代表的是IPv4协议(协议类型);
- 地址数据类型解析:
struct in_addr
{
u_int32_t s_addr;
};
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in
{
sa_family_t sa_family;
u_int16_t sin_port;
struct in_addr sin_addr;
}
struct sockaddr_un
{
sa_famliy_t sa_family;
....
}
struct sockaddr_in6
{
sa_famliy_t sa_family;
....
}
– socket函数支持多种不同的通信协议,每种通信协议都有一个特定的结构体,通过sa_family来判断当前使用的协议。
- IP地址相关函数
– #include<arpa/inet.h>
函数原型 | 功能描述 |
---|
in_addr_t inet_addr(const char* strptr); | 将IP字符串转换为符合网络字节序的整数 |
int inet_aton(const char* cp, struct in_addr* inp); | 将IP字符串转换为符合网络字节序的整数,成功返回1,失败返回0 |
char* inet_ntoa(struct in_addr in); | 将符合网络字节序的整数地址转换为字符串形式 |
– 当无法确认得到的IP字符串是否合法时,使用inet_aton函数,而不是inet_addr函数;
unsigned int addr = inet_addr("1.2.3.4");
struct in_addr addr1 = {0x09080706};
struct in_addr addr2 = {0x05040302};
#if 0
char* s1 = inet_ntoa(addr1);
char* s2 = inet_ntoa(addr2);
#else
char* s1 = strcpy(malloc(32), inet_ntoa(addr1));
char* s2 = strcpy(malloc(32), inet_ntoa(addr2));
#endif
printf("addr = %x\n",addr);
printf("s1 = %s\n",s1);
printf("s2 = %s\n",s2);
if(inet_aton("4.3.2.1",&addr1))
{
printf("addr1 = %x\n",addr1.s_addr);
}
free(s1);
free(s2);
- inet_ntoa每次被调用都会把先处理结果放在同一片内存中,再返回这片内存的地址,所以直接多次调用的话,新的会覆盖旧的;所以当需要多次使用时,每次使用后都需要把结果先读出;