分类: C/C++
2013-11-12 18:15:39
原文地址:socket编程-预备知识 作者:丫叩酱
一、IP地址
inet_aton 、inet_ntoa 、inet_addr
inet_pton 、inet_ntop
二、端口号
1. 协议栈???
什么是协议栈?
协议栈在哪里?
2. 分用???
每层协议盒要去检查 报文首部中的协议标识,以确定接受数据的上层协议。
网络数据依靠IP Address 进行路由(host-host)
数据包 依靠port 送达给接收进程(主机内部投递)
三、字节序
1. 字节序?
小端序:将低字节存储在起始地址
大端序:将高字节存储在起始地址
网络中传输的数据必须按网络字节序(即大端字节序)
2. 字节序转换??
#1. 凡是传给网络的参数, 都需要将 主机字节序 转为 网络字节序
端口号:htons() (short型数据)
IP地址:inet_pton()
#2. 凡是从网络取得的参数,都需要将 网络字节序 转为 主机字节序
端口号:ntohs() (short型数据)
IP地址:inet_ntop()
#3. 用户传输的数据,是否要转换,由用户协议来约定
建议采用网络字节序,这样有更好的扩展能力
3. 字节序转换函数??
主机到网路
uint32_t htonl(uint32_t hostlong);
uint16_t htonl(uint16_t hostlong);
网络到主机
uint32_t ntohl(uint32_t netlong);
uint16_t ntohl(uint16_t netlong);
四、地址结构
1. 地址结构类型:
#1. 通用地址结构,用于函数原型定义,相当于泛型参数
struct sockaddr
{
sa_family_t sa_family; /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};
#2. IPv4地址结构,用于IPv4协议族通讯
struct sockaddr_in
{
sa_family_t sin_family;
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
unsigned char sin_zero[8]; /* Pad to size of `struct sockaddr'. */
};
#3. IPv6地址结构,用于IPv6协议族通讯
struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
struct in6_addr
{
union
{
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
}in6_u;
}
#4. UNIX domain协议地址结构
strcut sockaddr_un
{
sa_family_t sun_family;
char sun_path[108];
}
2. 地址结构处理:
step 1,memset
定义一个#2~~#4的结构参数,并将它清零
step 2,set fields
为这个结构赋值
step 3, call functions, as parameter, cast to struct socketaddr
在函数调用中使用时,将这个结构强制转换为sockaddr类型,作为参数传递给bind()/connect等系统调用
五、数据
1. 数据类型
在网络通讯中,最好使用stdint.h定义的整形数据类型。
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t uint64_t
2. 传输数据处理
#1. 若需传输浮点型数据,需特别处理
>转换为整数,在发送时乘以系数,在接收时除以相应的系数,系数为10的整数倍。
#2. 若需传输负数,需特别处理
>将符号位和值(转为绝对值)单独传输
#3. 若需传输结构体,需谨慎处理对齐和填充的问题
>在协议设计时,主动进行对齐(推荐方式),或设置#progma pack(1)
六、协议族与地址族
从设计上来讲,protocol family支持多个address family,但将二者实现为一对一
1. 使用的一般规则
#1. 当传递给socket()函数的domain参数时,用PF_XXX
#2. 当传递给地址相关的处理函数时,用AF_XXX
2. 在Socket编程中,一下代码中的地址参数应该是一致的
#1. 创建socket时,调用socket()的domain参数
#2. 调用connect()/bind()/accept()/sendto()/recvfrom()的地址参数
#3. 地址参数中的family成员
七、寻址