理解源IP地址和⽬的IP地址:
IP在⽹络中,⽤来标识主机的唯⼀性
后⾯我们会讲 IP 的分类,后⾯会详细阐述 IP 的特点
认识端⼝号
端⼝号( port )是传输层协议的内容.
端⼝号是⼀个 2 字节 16 位的整数
端⼝号⽤来标识⼀个进程, 告诉操作系统, 当前的这个数据要交给哪⼀个进程来处理;
IP地址 + 端⼝号能够标识⽹络上的某⼀台主机的某⼀个进程;
⼀个端⼝号只能被⼀个进程占⽤

端⼝号范围划分
0 – 1023 : 知名端⼝号, HTTP, FTP, SSH 等这些⼴为使⽤的应⽤层协议, 他们的端⼝号都是固定的.
1024 – 65535 : 操作系统动态分配的端⼝号. 客⼾端程序的端⼝号, 就是由操作系统从这个范围分配的.
理解 “端⼝号” 和 “进程ID”
⼀个进程可以绑定多个端⼝号; 但是⼀个端⼝号不能被多个进程绑定;
理解源端⼝号和⽬的端⼝号
传输层协议( TCP 和 UDP )的数据段中有两个端⼝号, 分别叫做源端⼝号和⽬的端⼝号. 就是在描述 “数据是谁发的, 要发给谁”;
理解socket
IP 地址⽤来标识互联⽹中唯⼀的⼀台主机, port ⽤来标识该主机上唯⼀的⼀个⽹络进程
IP+Port 就能表⽰互联⽹中唯⼀的⼀个进程
所以,通信的时候,本质是两个互联⽹进程代表⼈来进⾏通信,{srcIp,srcPort,dstIp,dstPort}这样的4元组就能标识互联⽹中唯⼆的两个进程
所以,⽹络通信的本质,也是进程间通信
我们把 ip+port 叫做套接字 socket

传输层的典型代表
如果我们了解了系统,也了解了⽹络协议栈,我们就会清楚,传输层是属于内核的,那么我们要通过⽹络协议栈进⾏通信,必定调⽤的是传输层提供的系统调⽤,来进⾏的⽹络通信。
认识TCP协议
Tcp协议特点:
传输层协议
有连接
可靠传输
⾯向字节流
认识UDP协议
Udp协议特点:
传输层协议
⽆连接
不可靠传输
⾯向数据报
⽹络字节序
内存中的多字节数据相对于内存地址有⼤端和⼩端之分, 磁盘⽂件中的多字节数据相对于⽂件中的偏移地址也有⼤端⼩端之分, ⽹络数据流同样有⼤端⼩端之分. 那么如何定义⽹络数据流的地址呢?
1.发送主机通常将发送缓冲区中的数据按内存地址从低到⾼的顺序发出;
2.接收主机把从⽹络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到⾼的顺序保存;
3. 因此,⽹络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是⾼地址.
4. TCP/IP协议规定,⽹络数据流应采⽤⼤端字节序,即低地址⾼字节.
5. 不管这台主机是⼤端机还是⼩端机, 都会按照这个TCP/IP规定的⽹络字节序来发送/接收数据;
6. 如果当前发送主机是⼩端, 就需要先将数据转成⼤端; 否则就忽略, 直接发送即可;

为使⽹络程序具有可移植性,使同样的C代码在⼤端和⼩端计算机上编译后都能正常运⾏,可以调⽤以下库函数做⽹络字节序和主机字节序的转换。

这些函数名很好记, h 表⽰ host , n 表⽰ network , l 表⽰ 32 位⻓整数, s 表⽰ 16 位短整数。
例如 htonl 表⽰将 32 位的⻓整数从主机字节序转换为⽹络字节序,例如将IP地址转换后准备发送。
如果主机是⼩端字节序,这些函数将参数做相应的⼤⼩端转换然后返回;
如果主机是⼤端字节序,这些函数不做转换,将参数原封不动地返回
socket编程接⼝
// 创建 socket ⽂件描述符 (TCP/UDP, 客⼾端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端⼝号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建⽴连接 (TCP, 客⼾端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockaddr结构
socket API是⼀层抽象的⽹络编程接⼝,适⽤于各种底层⽹络协议,如IPv4、IPv6,以及后⾯要讲的UNIX Domain Socket. 然⽽, 各种⽹络协议的地址格式并不相同.

IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址⽤sockaddr_in结构体表⽰,包括16位地址类型, 16位端⼝号和32位IP地址.
IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的⾸地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容.
socket API可以都⽤struct sockaddr *类型表⽰, 在使⽤的时候需要强制转化成sockaddr_in; 这样的好处是程序的通⽤性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数;
sockaddr 结构

sockaddr_in 结构

in_addr结构

in_addr⽤来表⽰⼀个IPv4的IP地址. 其实就是⼀个32位的整数;
今天的更新就到这里,如有错误欢迎指出
评论
还没有任何评论,你来说两句吧!