IPv4套接字地址结构
struct in_addr
{
in_addr_t s_addr; //IP地址
}
struct sockaddr_in
{
uint8_t sin_len; //套接字长度,有的版本没有
sa_family_t sin_family; //协议族
in_port_t sin_port; //端口
struct in_addr sin_addr; //ip地址
char sin_zero; //填充位,一般用memset置为0
}
还有个通用的地址结构:
struct sockaddr
{
unit8_t sa_len;
sa_family_t sa_family;
char sa_data[14]
}
每个sockaddr_in 用bind时,总是要进行强制转换,例如
bind(sockfd,(struct sockaddr *) &serv, sizeof(serv));
唯一用途:指向特定于协议的套接字地址结构的指针执行类型强制转换。
IPv6套接字结构的最大特点是 struct in6_addr sin6_addr 是128位地址结构,而IPV4只有32位
地址族是AF_INET6
新的IPv6套接字结构,满足各种苛刻的对齐要求,容纳系统支持的任何套接字地址结构。
struct sockaddr_storage
{
unit8_t ss_len;
sa_famliy_t ss_family;
}
值-结果参数:
(1)从 进程 到 内核 传递套接字地址的函数为: bind、connect、sendto
例如connect(sockfd,(SA *) &serv, sizeof(serv))
(2)从 内核 到 进程 传递套接字地址的函数为 accept recvfrom getsockname getperrname
注意:这是值-结果传递
getpeername(unixfd, (SA*) &client, &len)
这个len是带取地址的
先给内核传入该结构的大小,然后 内核又会返回一个结果即存储的信息大小。
利用这个程序区别大端小端
char = 0x0102
//小端:char[0]存的是字节低位,即02
//大端:char[0]存的是字节高位,即01
union
{
short s;
char c[2]; //01 02
}
un,s=0x0102;
if( un.c[0]== 1 && un.c[1]==2 )
printf("big-endian");
else if( un.c[0] == 2 && un.c[1] == 1)
printf("little-endian!")
为了让用户不关心主机字节序和网络字节序,可利用to函数
uint16_t
h
to
n
s
h是主机,n是network, s是short,16位,l是long,32位。
uint32_t
htonl
uint16_t
ntohs
uint32_t
ntohl
字节操纵函数
bzero 把指定数目的字节置零
bcopy 类似于字节复制
bcmp 字节串比较,相同为0,不同为非0
memset 指定字节串的字节置为同一值
memcpy 类似于bcopy
memcmp 类似于bcmp
地址转换函数
inet_aton 把192.232.132.232转为32位二进制网络字节 ,并传递到参数里,返回错误信息
inet_addr 返回二进制字节,但是这样导致无法处理32位全1的广播地址,因为32位全1是出错的意思。
inet_ntoa 把二进制网络字节转为 点分十进制IP地址
inet_pton
inet_ntop
p是表达presentation,n是数值numeri
即p是IP的表达字符串,n是给计算机读的二进制字节流(1001010010)
套接字IO
用write和read可能会输入输出的字数比请求少,但这不代表错,只是需要继续调用罢了,所以引入readn、writen和realine三个函数