章节号也何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) |