网络基础(一)

数据传输( (不)同主机上的进程间同信)

协议:(通信双方的一个数据格式协议)

网络中主机之间进行通信也必须使用相同的协议(相同的一个光电信号格式)

计算机如何传播数据—-光电波信号

在网络中因为主机设备的生产厂商很多,每个厂商如果都使用自己的协议进行通信,那么将导致网络上主机间无法正常通信,于是设计了一个标准的协议

网络间的数据传输就必须使用同一个标准协议 ——-网络通信协议

在网络通信中,因为应对场景各有不同,因此协议也相对特别复杂,为了使用起来更加方便,因此就有了协议的封装/分层。

协议的封装/分层:按照各个协议的不同功能以及不同的应对场景对不同的协议进行了分层,在特定的环境下如果协议的分层清晰明了,那么使用/替换起来就更加方便

OSI网络互联七层参考模型:

优点:1.将服务,接口和协议明确区分开来

应用层 表示层 会话层 传输层 网络层 数据链路层 物理层

TCP/IP五层模型:

TCP/IP五层模型:TCP/IP指的是一个协议簇,因为TCP协议和IP协议是最典型的两个协议,因此这个协议簇就拿这两个协议名字进行命名了

应用层 :负责应用程序间的数据沟通 http/https ftp

传输层(内部完成):负责端与端之间的数据传输(进程与进程间)TCP/UDP

网络层:负责地址管理和路由选择 IP (路由器)

数据链路层:负责相邻设备节点间的数据传输 以太网协议 交换机

物理层:负责光电信号的传输 以太网协议 集线器

数据的传输流程:

1.不同的协议层对数据包有不同的称谓,在传输层叫做段,在网络层叫做数据报,在链路层叫做帧

2.应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部,称为封装

3.首部信息中包含了一些类似于首部有多长,载荷有多长,上层协议是什么等信息

4.数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的“上层协议字段”将数据交给对应的上层协议处理

数据封装

套接字编程——–原始的网络socket编程

IP地址:唯一定位网络上的主机(无符号四个字节的整数——uint32_t)

端口:标识一台主机上的进程(无符号两个字节的数据 uint16_t ,0~65535)

进程的标识为什么不用PID?

因为PID会随着进程的创建改变的

sip+sport+dip+dport+proto 五元组

网络字节序:大小端

大端字节序:低地址存高位

0x01 02 03 04 uchar buf[4] 01 02 03 04

小端字节序:低地址存低位

uchar buf[4] 04 03 02 01

所以不同字节序主机之间进行数据传输,将造成数据的逆序,也就是得不到人家真正发送的数据。因此,约定了在网络间进行通信时必须使用大端字节序—-网络字节序,也就意味着如果我们的主机时小端字节序,那么通信时就需要对数据逆序,但是并不是所有数据都需要逆序,主要针对在内存中存储时,占据字节大于1个字节的数据(short,int,float,double,long等,针对这些类型的是数据,因为在内存中的存储跟展示顺序刚好相反,而发送时按字节发送对方按字节接收,那么如果对方时大端,因为低地址存高位,因为存储顺序和使用顺序完全相同,导致数据跟实际想发送的数据顺序刚好相反,因此需要进行字节逆序转换)

主机字节序:当前主机的字节序—–大小端不一定,取决于CPU的架构

x86(小端) MIP5(大端) RISC-V

网络套接字编程:(主要说的时传输层的TCP/UDP)

因为传输层有两个传输协议,所以必须选择其一进行数据传输,那么如何选择?

答:TCP:面向连接,可靠传输,字节流服务

优点:可靠传输,并且传输灵活 缺点:传输速度低,数据粘包

UDP:无连接,不可靠,面向数据报

优点:传输数据快,无粘包 缺点:不可靠

针对数据安全性要求高的场景(文件传输):使用TCP保证数据的可靠

安全性要求不是很高但是实时性要求高的场景(视频传输):使用UDP保证传输速度

socket套接字编程:

网络编程涉及到对网卡的操作,因此操作系统就提供了一套接口—socket接口

网络编程中分了两个端:客户端程序和服务端程序(在网络编程中,客户端是主动的一方,并且客户端必须知道服务端的地址信息ip+port,而服务端需要在这个指定的地址等着)

UDP编程步骤:

服务端: 创建套接字(建立网卡与进程之间的关系)

为套接字绑定地址信息(声明去网卡接收数据时找所需要的正确数据)

接收/发送数据

关闭套接字

客户端:创建套接字

​ 绑定(由操作系统自己完成,不主动绑定)

​ 发送/接收数据

​ 关闭套接字

服务端必须绑定地址,因为服务端是被动的一端,必须告诉别人需要将数据发送到哪个地址哪个端口,因此自己就必须接收这个地址这个端口的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
1.int socket(int domain, int type, int protocol);

domain:地址域 AF_INET IPV4

type:套接字类型

SOCK_STREAM 流式套接字 TCP

SOCK_DGRAM 数据报套接字 UDP

pro: 协议类型

IPPROTO——TCP 6 TCP协议

IPPROTO——UDP 17 UDP协议

返回值:非负整数(套接字描述符) 失败:-1

2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:套接字描述符

addr:地址信息

addrlen:地址信息长度

返回值:成功:0 失败:-1

uint16_t htons(uint16_t hostshort);

将一个短整型(16位)数据从主机字节序转换成网络字节序

in_addr_t inet_addr(const char *cp);

将点分十进制的字符串IP地址转换为网络字节序的地址

INADDR_ANY:只能用于服务端(0.0.0.0)

3.ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,

struct sockaddr *src_addr, socklen_t *addrlen);

sockfd:套接字描述符

buf:要发送的数据

len:发送的数据长度

flags:发送标志 一般给0,默认阻塞

MSG_PEEK 接收数据后数据不会立即从缓冲区删除

场景:探测型获取数据

src_addr:发送端的地址信息

addrlen:地址信息长度

返回值:实际读取到的字节长度

assign:从一个字符串中拷贝指定长度的数据到string中

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,

const struct sockaddr *dest_addr, socklen_t addrlen);

sockfd:套接字描述符

buf:要发送的数据

len:发送的数据长度

flags:发送标志 一般给0,默认阻塞

dest_addr:数据要发送到的对端地址信息

addrlen:地址信息长度

返回值:实际发送的数据长度 失败:-1

4.close(sockfd) 关闭套接字释放资源
0%