章节号也何UNP上的一样,省得乱了。
3.2 套接口地址结构
在<netinet/in.h>中声明了IPV4的地址结构
struct in_addr{
in_addr_t s_addr; //32b
};
struct sockaddr_in{
uint8_t sin_len;
sa_family_t sa_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
通用套接口地址结构
套接口地址结构总是通过指针来传递,那么这个指针的数据类型就是通用套接口类型
struct sockaddr{
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};
这也使得,套接口函数要转换成只想通用套接口地址结构的指针
bind(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
3.3 值-结果参数
套接口地址结构的长度作为参数来传递,其传递方式取决于结构的传递方向:从进程到内核,还是内核到进程
1 进程——》内核
bind, connect, sendto.这3个函数的一个参数是只想套接口地址结构的指针,另一个参数是结构的大小
由于指针和指针所指结构的大小都传递给内核,故可知进程到内核的数据长度。
2 内核——》进程
accept,recvfrom,getsockname,getpeername
这4个函数的一个参数是只想套接口地址的指针,另一个参数是自相结构大小的指针
为何将结构大小给为指向整数的指针呢?当函数被调用时,结构大小是一个值(value,告诉内核该结构的大小),返回时,结构大小又是一个结果(result,告诉进程,内核在此结构中存储了多少信息)。这种参数叫做 值——结果参数
用户进程 内核
----------------》值
结构长度
《----------------结果
套接口地址结构《------------协议地址
3.4 字节排序函数
低(字节)底(内存地址)为小(端)
高底为大
(host byte order)linux 采用小端,而solaris,aix,macos,freebsd5,hpux都是大端,
(network byte order)则统一采用大端。
那么由此产生了需要将 HBO与NBO进行 转换的必要
#include <netinet/in.h>
uint16_t htons(host)
uint32_t htonl(host)
//HBO-》NBO
uint16_t ntohs(network)
uint32_t ntohl(network)
//NBO->HBO
3.5 字节操纵函数
因为像IP地址这类的数据,它中间有0,但有不是C字符串,不能使用strxxx函数。
但是有两类功能相同的处理函数
1 Berkeley函数
#include <strings.h>
void bzero(void* dest,size_t nbytes);
void bcopy(const void *src,void* dest,size_t nbytes);
int bcmp(const void*ptr1,const void* ptr2,size_t nbytes)
// const void *ptr 函数只能读取而不能修改指针所指的内存单元
2 ANSI C函数
#include <string.h>
void *memset(void *dest,int c,size_t nbytes);
void *memcpy(void *dest,const void* src,size_t nbytes);
int memcmp(const void*ptr1,const void* ptr2,size_t nbytes);
//记忆的话就是长度都是作为最后一个参数
3.6 字节转换函数
在ASCII字符串(192.168.1.45)<——>NBO的二进制值
p:presentation(ASCII)
n:numeric(NETWORK)
#include <arpa/inet.h>
int inet_pton(int family,const char *strptr,void *addrptr);
1-成功,0-输入错误
//strptr->addrptr
const char *inet_ntop(int family,const void* addrptr,char *strptr,size_t len);
//addrptr->strptr
IPV4中设置 len为16(4*4)