UNP第三章总结。

来源:互联网 发布:封装js插件 编辑:程序博客网 时间:2024/05/22 08:25

第三章主要讲的是套接口的一些结构和一些类型转换函数。。

3.2 套接口地质结构。

IPV4套接口地址结构:<netinet/in,h>   结构名字 sockaddr_in

struct sockaddr_in                                                                                                                                                                                

{

   uint8_t sin_len; 地址的结构长度,这个参数有时会是函数的参数。有时候也会用sizeof(结构)代替函数的参数

   sa_family_t sin_family; 协议族,IPV4是AF_INET;

   in_port_t sin_port; 16位的TCP/UDP端口地址                                                                                                                   

   struct in_addr sin_addr;  存储32位IPV4的地址结构 

   char sin_zero[8];  暂时不用。总是置为0                                                                                                                               

}                

     struct in_addr  {                                                                    

       in_addr_t s_addr;  32位Ipv4地址

}                                                                                          };

说实话,挺难记的。开头都是sin_   后面跟着长度len,协议族family 端口port   Ipv4地址结构addr 

长度其实一共是1+1+2+4+8*1=16字节。

 

然后理理UNP第三章的思路,先讲了Ipv4地址结构,之后这些地址结构是要拿来用的,很经常用作函数的参数,我们知道这结构体长度是16个字节,传递过去是十分浪费空间以及时间的,所以我们是传递一个指针。

然后自然而然讲到了指针,ANSI C是有一个void*的指针类型,但在ANSI C之前已经有了套接口函数了,那时候我们是在 <sys/socket.h> 头文件中定义了一个通用的套接口地址结构

struct sockaddr

{

    uint8_t sa_len;    结构体长度                                                                                                

   sa_family_t sa_family; 协议族                             

   char sa_data[14]; 存储某些协议的特定地址

}

   ————>>>应用举例

   struct sockaddr_in serv;

 bind(sockfd,(struct sockaddr *)&serv,sizeof(serv));    



Ipv6套接口地质结构  <netinet/in.h>   结构名字:sockaddr_in6

struct sockaddr_in6

{

   uint8_t sin6_len;  结构长度

    uint8_t sin6_family;   协议组 AF_INET6

   sa_family_t sin6_port;  端口号

   uint32_t sin6_flowinfo;   The IPv6 flow information                                                          

    struct in6_addr;  Ipv6地址结构

   uint32_t si6_scope_id;                                                                                                                 

}                               

 struct in6_addr{

 uint8_ts6_addr[16];  16*8=128位Ipv6地址           

       }

之后的思路跟讲解Ipv4的思路是一样的。又提出了新的通用套接口地址结构: sockaddr_storage

这个结构体十分有趣,必须强制类型转换为合适的地址类型的套接口地址结构,才可以访问其他字段。初始只可以访问两个内部成员

struct sockaddr_storage

{

    uint8_t ss_len;

    sa_family_t ss_family;

其他数据用户透明

}

其实这些东西写一遍后就比较清楚了,光看不行。。。。

 

3.3 值-结果参数

进程到内核: 长度 值传递  套接口地址结构:指针传递(或者说地址值传递)

内核到进程:  长度 指针传递 套接口地址结构:指针传递

 

3.4 字节排序函数

首先讲的是小端字节序和大端字节序。

先了解两个基础:

  ————————>>>内存增大

 数组[0] [1] [2] [……] [n-1]

对于一个16位数 MSB……LSB

然后开始讲述什么是大端什么是小端。大端表示存取数据时先把高字节放上去,就是把MSB边的位先放上去,何为先放上去,我们放数据位都是先放在内存地址小的地方,然后再放到更高的内存地址的地方。其实说白了就是存的时候先把高位存上去(存在内存地址较低地方),之后再存低位的。

小端刚好相反。

书中有一个例子,其中对于验证这种东西是用了union结构,之前还好看完了C和指针,(*^__^*) 嘻嘻……大一学的C++好浅,联合都没有讲。

我测试的ubuntu14.10是小端字节序的。。


上面说的是主机字节序,指的是给定系统所用的字节序,其中就有大端字节序和小端字节序。

有点心烦。不过发现打完一遍好像都复习了。

网络协议必须指定一个网络字节序,就是数据发送先发送高字节还是低字节么??这个暂时我是这么理解的。然后给出了主机字节序和网络字节序的转换函数,共4个。

#include <netinet/in.h>

uint16_t htons(uint16_t host16bitvalue)

uint32_t htonl(uint32_t host32bitvalue)

                                                                返回网络字节序host to net short/long

uint16_t ntohs(uint16_t net16bitvalue)

uint32_t ntohl(uint32_t net32bitvalue)

                                                                返回主机字节序值net to host short/long


3.5 字节操纵函数

我们在大一学的<string.h>str开头的那些函数处理的对象是以空字符结束的C字符串,但IP地址中很长出现多个字节的0.

于是提出了新的字节操作函数。

第一组函数,以b开头的,表示byte(字节)。现在仍然几乎任何支持套接口函数的系统提供。

#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)                        0相等否则不相等

几乎从函数名字就知道是干啥的,不提了。

第二组函数:以mem开头,表示memory,支持ANSI C库的系统

#include <string.h>

void *memset(void *dest,int c,size_t len)

void *memcpy(void *dest,const void *src,size_t nbytes)

int memcmp(const void *ptr1,const void *ptr2,size_t nbytes)        0相等否则不相等


3.6书中说了几个函数当3.6节的名字,我管它点分十进制数串(char*)与网络字节序的二进制值(struct in_addr*)之间的地址转换函数。

其实3.6节讲的是Ipv4的。

点分十进制数串:对是数串,本质是char *. 比如   “206.168.112.96”    (注意这两边双引号)

网络字节序二进制值:struct in_addr 前面已提到了IPV4的地址结构(32位)

#include <arpa/inet.h>

int inet_aton(const char*strptr,struct in_addr *addrptr)

这个函数先检查点分十进制数串strptr(char *)是否有效,如果有效,则转换为32位网络字节序二进制存入addrptr指向的结构体中。若addrptr为空指针则只进行字符串strptr有效性检查。  串有效返回1,串出错返回0。


in_addr_t inet_addr(const char *strptr)

把strptr转换为32位二进制的网络字节序地址并且返回,有错则返回INADDR_NONE(为32位均为1的值)。由于出错返回的是32位均为1的值,也就是说,如果转换出32位二进制网络字节序刚好也是32位均为1,即255.255.255.255此时会被指示为函数失败。

char *inet_ntoa(struct in_addr inaddr)

将一个32位的网络字节序二进制ipv4值转换为相应的点分十进制数串。有趣的是参数是一个结构体而不是结构体指针


3.7更新的地址转换函数。(IPV4和ipv6均可以用哟~)

地址的表达(presentation)通常是ASCII串,数值格式则是存在于套接口地址结构中的二进制值

#include <arpa/inet.h>

int inet_pton(int family,const char *strptr,void *addrptr)

const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);

p指的是presentation,n指的是numeric(数值)


未完待续……

 

0 0