UNIX网络编程第三章读书笔记

本章主要说套接口编程,先说下基本的结构体:

struct sockaddr_in 

{

uint_8 sin_len;

sa_family_t  sin_family;

in_port_t      sin_port;

struct in_addr  sin_addr;

char sin_zero[8]

}

typedef uint16_t  in_port_t;

typedef uint32_t in_addr_t;

struct in_addr

{

in_addr_t  s_addr

}

这个结构体成员的名字挺难记得,我是这样总结的:

首先sockaddr_in是最直接操作的结构体,sockaddr是套接字通用的前缀,in指的更多的是ip协议;

里面的成员都加一个sin前缀,对于套接字需要澄清的是端口(sin_port)IP地址(sin_addr),协议类型(sin_family)

sin_port端口最大是65536,两个字节就可以表示,所以其类型为双字节类型,uint_16

sin_addr对于ipv4就是四个不超过255的点分十进制,整合起来就是一个4字节的无符号整形 uint_32即可

sin_family 对应的就是v4还是v6,打印了大小是两个字节

需要说明的是sin_addr有点特殊,历史上是想能够更快的拿到网络地址主机地址,所以之前是个枚举类型;后来就废除了,改成了只有一个成员的结构体?

记忆这个sin_addr我是这样记忆的,首先从最上面大家都是sin_addr,

它的类型是结构体,那就是strut ***,

类型比变量名字少一个s,

成了strut in_addr sin_addr; 

接下来就是说struct in_addr这个类型了

它里面是只有一个成员的结构体,

struct in_addr{

in_addr_t s_addr;

}

注意观察,成员的类型成了in_addr_t,变量名字变成了s_addr,要么是sin 要么是s,要么是in,哈哈,就这样组合;

有点绕,大概就这样就可以记住了。



协议类型比较多,就造成套接口地址结构比较多,调用bind又就期望可以有一个通用的版本,这样通用套接口地址结构就出现了,刚才看到sockaddr_in表示的是ipv4,那通用的就用struct sockaddr来表示,其结构如下:

struct sockaddr {

uint8 sa_len;

sa_family_t sa_family

char  sa_data[14];

}

bind函数的调用方式就成为

bind(fd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));

这里有个点,为什么需要第三个参数,因为不是所有的套接口结构体大小都是定长的,比如unix域协议。


值结果参数:

说的意思就是:调用函数是传递值进去,但是函数返回时也会把需要返回的信息通过参数传递出来。两个作用一起。

比如getsockname和getpeername等


字节排序函数

主要提到了大端小端以及字节序转换函数

大端小端最专业的解释是:大端或者小端表示在多字节值里,哪一端(大端或者小端,或者叫数据权重高低--个人理解)放在该值的起始地址

大端表示,高权重位放在该值的起始地址,比如我们经常写的12345,1是高权重位,但是放在低地址,当然默认是地址从小到大。

小端相反。

测试用例如下:

#include "stdio.h"


union b_s_endian_t
{
        short svalue;
        char schar[2];
};


int main()
{
        union b_s_endian_t b_s_endian_value;
        b_s_endian_value.svalue=0x1234;
        if(b_s_endian_value.schar[0] == 0x12)
                printf("big endian\n");
        else if(b_s_endian_value.schar[0] == 0x34)
                printf("small endian\n");
        else
                printf("occur error\n");
        return 0;
}

在intel CPU下面运行是小端模式,大端小端是由硬件决定的,跟软件没有关系。

在网络通信中,两端使用的字节序是不一样的,这个时候就需要一个通用标准,标准规定网络通信中使用大端模式。

htons 把一个short类型的主机字节序转为网络字节序

htonl  把一个long类型的主机字节序转为网络字节序

ntohs

ntohl 类比上面



字节操纵函数:

string.h里面操纵的都是以NULL结尾的字符串

b开头的,比如bzero等是起源于BSD

mem开头的是起源于ANSI C标准

bzero bcopy bcmp

memset  memcopy memcmp

需要说明的是:

当需要dest和src一样时, bcopy可以正确处理,

memcopy处理结果却是未知的,不过可以使用memmove函数。


地址转换函数:

通常大家写ip地址都喜欢使用字符串,直观清楚明了,但是在网络编程里面结构体里面定义的是一个uint_32类型。就需要把字符串转换为无符号整形。

inet_aton 点分十进制转为网络地址

inet_ntoa 网络地址转为点分十进制

inet_addr 点分十进制转为网络地址,返回类型死in_addr_t类型,对应的是sin_addr.s_addr的类型。

需要说明的是:

inet_aton inet_ntoa只是针对ipv4操作的函数,不能兼容ipv6;

inet_addr在操作255.255.255.255时会出问题,因为返回失败的值和255.255.255.255正确返回时一样,加之没有正式标准。

都是线程不安全函数。


inet_pton

inet_ntop对ipv4和ipv6都适用


需要指出的:stdio提供的函数是有内部缓冲区的,所以上层应用调用时需要留意。


猜你喜欢

转载自blog.csdn.net/xiaoyilong2007101095/article/details/80027326