1 IP地址和端口号
1.1 IP为网络协议的简称,为了收发网络数据分配给计算机的值。端口号则为区分程序中创建的套接字而分配给套接字的序号。
IPV4 4字节地址族
IPV6 16字节地址族
1.2 IPv4 地址可以分为四种类型
A类:1字节网络ID,3字节主机ID 首字节范围:0-127
B类:2字节网络ID,2字节主机ID 首字节范围:128-191
C类:3字节网络ID,1字节主机ID 首字节范围:192-223
D类:4字节网络ID
数据传输时,通过网络Id找到网络地址,之后通过主机ID找到该网络下的主机地址
1.3端口号
端口号在同一操作系统下区分不同套接字设置,无法将同一端口号分配给不同套接字。
端口号由16位组成,端口号的取值范围为:0-2^16-1,0-1023为指定端口号,一般分配给特定程序。TCP套接字和UDP套接字不共用端口号。
2地址信息表示
2.1 地址信息采用结构体表示:
struct sockaddr_in
{
sa_family_t sin_family; //地址族
uint16_t sin_port; //端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用
}
struct in_addr
{
In_addr_t s_addr; //32位IPv4的地址
}
2.2 uint16_t,in_addr,sa_family_t等类型为POSIX定义的类型。
uint16_t头文件为:sys/types.h
sa_family_t头文件为:sys/socket.h
in_addr_t头文件为:netinet/in.h
sin_family为地址族信息:
AF_INET:IPv4网络协议中使用的地址族
AF_INET6:IPv6网络协议中使用的地址族
AF_LOCAL:本地通信中采用的UNIX协议的地址族
成员sin_port 位16位的无符号整数,以网络字节序保存!
成员sin_addr in_add_r为32位整数
成员sin_zero无特殊含义,用来保持结构体sockaddr_in的大小与sockaddr结构体保持一致,而插入的成员,全部填充位0
2.3 bind和sockaddr
struct socketaddr_in serv_addr;
if(bind(serv_sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1)
error_handling("bind()error");
第一个参数为socket ,第二个参数为地址信息
struct sockaddr{
sa_family_t sin_family;
char sa_data[14];
}
sa_data中存储地址IP和端口号,对于IPv4地址,IP地址为32位,4字节,端口号16位,2字节,此时对应上面sin_zero[8]为8个字节,刚好为sa_data的大小,14字节。
2.4 网络字节序
CPU保存数据的形式为:大端序和小端序。
大端序:高位字节放在低位地址。
小端序:高位字节放在高位地址。
网络字节序统一采用大端序。
字节序转换:
h:主机字节序
n:网络字节序
s:short型数据
l:long型数据(Linux中long型数据占用4个字节)
htons:将short型数据从主机字节序转换为网络字节序
unsigned short host_port=0x1234;
unsigned short net_port;
unsigned long host_addr=0x12345678;
unsigned long net_addr;
net_port=htons(host_port);
net_addr=htonl(host_addr);
注:实际使用中,除了向sockaddr_in结构体变量填充数据,其他情况无需考虑字节序问题,均为自动转换。
3网络地址初始化和分配
3.1字符串信息转换为网络字节序的整数型
对于IP地址,常用的为点分十进制表示法,而不是整型数据表示法,可以通过某个函数来实现将字符串形式的IP地址转换为32位的整数型数据。
#include<arpa/inet.h>
in_addr_t inet_addr(const char* string);
//成功返回32位大端序整数型值,失败返回INADDR_NONE;
//实际应用:
char *addr1="1.2.3.4";
unsigned long conv_addr=inet(addr1);
该函数不仅可以将IP地址转换成32位整数型,而且可以检测无效的IP地址
inet_aton函数与inet_addr函数功能相同,但其利用到了in_addr结构体,因此使用频率更高
#include<arpa/inet.h>
int inet_aton(const char* string,struct in_addr* addr);
//成功时返回1(true),失败时返回0(false)
//实际使用:
char *addr="127.232.124.79";
struct sockaddr_in addr_inet;
inet_aton(addr,&addr_inet.sin_addr);
3.2 网络字节序整数型IP地址转换位字符串形式
inet_ntoa函数
#include<arpa/inet.h>
char* inet_ntoa(struct in_addr adr);
//该函数直接返回一个字符串地址,即该字符串已经分配地址,但并未由程序员主动分配,完成后需要将该字符串复制并保存
//实际使用:
struct sockaddr_in addr1;
char* str_ptr;
char str_arr[20];
addr1.sin_addr.s_addr=hton(0x1020304);
str_ptr=inet_ntoa(addr1.sin_addr);
strcpy(str_arr,str_ptr);
3.3 网络初始化:
struct socket_in addr;
char* serv_ip="211.217.168.13";
char* serv_port="9190";
memset(&addr,0.sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(serv_ip);
addr.sin_port=htons(atoi(serv_port));//atoi函数将字符串类型的值转换为整数型。