【 一 】网络通信实现
【 1 】实现网络通信的四要素
-
本机的ip地址
-
子网掩码
-
网关的IP地址
-
DNS的IP地址( 域名系统)
DNS服务器是指提供域名解析服务的服务器。它负责将域名转换为相应的IP地址,以便计算机可以通过IP地址与其他设备进行通信。
通过使用DNS服务器,计算机可以方便地将域名转换为IP地址,并与其他设备进行通信。这在互联网中起到了至关重要的作用。
【2】获取四要素的两种方式
(1) 静态获取
-
即手动配置
(2)动态获取
-
通过dhcp获取
以太网头 IP 头 udp头 dhcp数据包
-
最前面的”以太网标头”,设置发出方(本机)的MAC地址和接收(DHCP服务器)的MAC地址。前者就是本机网卡的MAC地址,后者这时不知道,就填入一个广播地址:00:1A:2B:3C:4D:5E)。
-
后面的‘IP标头’,设置发出的IP地址和接收方的IP地址。这时,对于这两者, 本机都不知道。 于是, 发出方的IP地址就设为0.0.0.0,接收方的IP地址设为255.255.255.255
-
最后面的‘UDP标头’, 设置发出方的端口和接收方的端口。这一部分是DHCP协议规定好的,发出方是68端口,接收方是67端口
-
DHCP数据包(DHCP Packet) : DHCP数据包是动态主机配置协议 (DHCP)中用于自动分配网络配置的信息交换单元。 DHCP数据包由于以下字段组成:
-
操作码: 指明数据包的类型, 如请求、回复等。
-
硬件地址: 指明客户端设备的物理地址, 通常是MAC地址。
-
选项信息: 包括IP地址租约时间、子网掩码、默认网关等配置参数。
-
【 二 】DNS域名解析
【 1 】DNS的作用
DNS(Domain Name System,域名系统)是一种用于将域名转换成IP地址的分布式数据库系统。
(1)DNS的作用
-
域名解析:最基本的作用是将域名解析为对应的IP地址。当用户在浏览器中输入一个域名时,操作系统会向本地DNS服务器发送查询请求,本地DNS服务器会递归地向其它DNS服务器查询,直到找到该域名对应的IP地址。然后,操作系统将获取到的IP地址返回给浏览器,浏览器通过该IP地址与服务器建立连接。
-
负载均衡:DNS还可以用于实现负载均衡。当一个域名对应多个IP地址时,DNS服务器可以根据配置的策略将请求分发到不同的服务器上,从而均衡地分担服务器的负载,提高系统的性能和可用性。
-
邮件传递:DNS在邮件系统中也扮演重要角色。MX记录指定了接收邮件的服务器地址,当发送邮件时,邮件服务器会查找目标域名的MX记录,将邮件发送到相应的服务器上。
-
安全性:DNS在安全方面也起到关键作用。例如,DNSSEC(DNS Security Extensions)可以提供域名数据的数字签名,确保域名解析结果的真实性和完整性,防止DNS劫持和欺骗攻击。
总之,DNS的作用是通过将域名解析为对应的IP地址,实现互联网上不同计算机和服务之间的可访问性。同时,DNS还可以用于负载均衡、邮件传递和安全性保证等方面,为互联网的正常运行提供了重要支持。
(2)为什么一定要设置DNS才能上网
有一些客户端应用是打不开网页的,其实大部分原因都是因为DNS服务器故障造成的, DNS服务器地址是唯一的。它们是设定不了DNS服务器地址,那么就无法查询地址的去向,自然也就打不开网页。
而QQ、微信等聊天软件,它们采用的协议是不一样的UDP传输协议, 即不可靠传输协议,无需提供DNS服务器地址, 也同样可以登陆。
【2】DNS的两种查询方式
(1)递归
-
主机向本地域名服务器的查询一般都是采用递归查询。
-
所谓递归查询就是:
-
如果主机询问的本地域名服务器不知道被查询的域名IP地址
-
那么本地域名服务器就以DNS客户的身份,向其他根域名服务器继续发出查询请求报文(即替主机继续查询)
-
而不是让主机自己进行下一步查询。
因此,递归查询返回的查询结果或者是所要查询的IP地址,或者是报错,表示无法查询到所需的IP地址。
-
(2)迭代
-
本地域名服务器向根域名服务器的查询的迭代查询。
-
迭代查询的特点:
-
当根域名服务器收到本地域名服务器发出的迭代查询请求报文时
-
要么个所要查询的IP地址
-
要么高数本地服务器: ‘你下一本应当向哪一个域名服务器进行查询。’
-
-
然后让本地服务器进行后续的查询。
-
根域名服务器通常是把自己知道的停机域名服务器的IP地址高数本地狱名服务器,让本地域名服务器再向停机域名服务器查询。
-
顶级域名服务器在收到本地域名服务器的查询请求后
-
要么给出所要查询的IP地址
-
要么高数本地服务器下一步应当想哪一个权限域名服务器进行查询。
-
-
最后,知道了所要解析的IP地址或报错,然后把这个结果返回给发起查询的主机
总结:
递归查询在查询过程中只向DNS服务器发起一次请求,DNS服务器一直查找直到找到所需的解析记录,然后返回给客户端。
而迭代查询则是向DNS服务器发起多次请求,每次请求都会返回指向下一个域名服务器的IP地址或被告知去联系另一个DNS服务器,客户端需要不断向本地DNS服务器发送查询请求,直到回去到最终的IP地址。
-
【三】Scoket
【1】Scoket层在哪
【2】什么是scoket
Scoket是可以理解为一种抽象端点,它可以用来建立网络连接、发送和接收数据。通过Socket,应用程序可以在不同的计算机之间进行数据交换,实现客户端与服务器之间的通信。
总之:Scoket是一种用于实现网络通信的编程接口,它允许应用程序通过网络在不同的计算机之间进行数据传输和通信。
【3】套接字发展史以及分类
1971年, 美国的伯克利大学开发了第一个实现套接字概念的Unix操作系统。也就是BSD Unix.
分类:
- 流式套接字(SOCK_STREAM):提供可靠、面向连接的通信方式,例如TCP协议。
- 数据报套接字(SOCK_DGRAM):提供无连接、不可靠的通信方式,例如UDP协议。
- 原始套接字(SOCK_RAW):可以直接访问底层网络协议,例如IP协议和ICMP协议。主要用于网络管理和安全领域。
- 序列包套接字(SOCK_SEQPACKET):提供可靠的数据传输服务,保证数据包按照顺序到达。
(1)基于文件型
-
基于文件系统实现的套接字。
-
使用UNIX域协议 (Unix Domain Protocol) 进行通信
-
适用于进程通信(IPC), 在同一台主机上的进程可以通过该类型套接字互相通信。
(2)网络型套接字
-
基于网络协议实现的套接字。
-
包括TCP套接字和UDP套接字, 使用TCP/IP协议进行通信。
-
适用于网络通信, 可以实现跨主机的进程通信。
需要注意的是, 套接字作为一种通信接口, 实际上并不是文件, 只是UNIX系统中一文件描述的形式存在。因此,我们可以将套接字分为文件型套接字和网络型套接字,以便更好地区分它们的特点和使用场景。
【 四 】TCP协议
TCP(传输控制协议)是一种可靠的、面向连接的网络传输协议,它在计算机网络中提供可靠的数据传输。下面是使用TCP协议的一般流程:
-
服务器端创建Socket:服务器应用程序首先创建一个Socket对象,并绑定到特定的IP地址和端口号上,以侦听客户端的连接请求。
-
客户端创建Socket:客户端应用程序创建一个Socket对象,并指定服务器的IP地址和端口号,尝试连接到服务器。
-
三次握手建立连接:客户端向服务器发送连接请求报文段,服务器接收到请求后可以同意连接,回复一个确认报文段,客户端再发送一个确认报文段,完成连接的建立。
-
数据传输:连接建立后,客户端和服务器之间可以通过Socket对象进行数据传输。应用程序可以使用Socket API提供的函数,将数据写入Socket发送给对方,对方则可以通过Socket接收数据。
-
四次挥手断开连接:当连接不再需要时,任何一方都可以发送断开连接的请求,并等待对方的确认。双方都发送了断开请求并确认后,连接才会完全关闭。
在IPv4协议中,本地回环地址是127.0.0.1,
在使用TCP协议进行数据传输时,TCP提供了许多功能,如分段、序列号、确认和重传等,以确保数据的可靠性和顺序性。这使得TCP成为应用层协议(如HTTP、FTP等)的常用传输协议,用于可靠地传输数据。
【五】什么是socket粘包
【1】什么是socket的粘包
Socket粘包是值在网络通信中, 由于数据传输的不可预测性,导致接受无法准确的确区分和解析接收到的数据包,使得多个数据包黏在一起,形成一个较大的粘包。这种情况可能会影响同学的可靠性和正确性。
造成Socket粘包的主要原因有两个:
-
TCP协议的特性: TCP是面向流的协议,它提供的是一个字节流的传输,而不是固定大小的的消息。发送方写入的数据以字节为单位被传输,而接收方则以字节为单位进行读取。这就导致了接收方法无法知道数据的边界,容易将多个发送方的小消息喝不成一个大消息,或者将一个大消息拆分成多个小消息
-
发送频率较快:如果发送方的数据发送速度很快,而接收发的处理速度较慢,接收方可能在处理一个数据包时已经接收到了下一个数据包,从而形成粘包。
解决Socket粘包问题的方法:
-
消息边界:在消息中包含消息的长度信息, 这样接收方就可以根据长度信息准确地划分出每个完整的消息。这可以通过在消息头部添加长度字段实现。
-
定界符:使用特殊的字符或序列作为消息的定界符,表示一个消息的结束。接收方通过检测定界符来确定消息的边界。
-
使用更高层次的协议:例如:使用HTTP或者其他应用层协议,他们通常已经定义了消息的格式和边界。
-
使用缓冲区:接收方可以使用缓冲区逐步接收数据,并根据特定的规则来提取完整的消息。
【2】解决粘包现象的思路
(1)服务端
先计算总数据长度 ----> 打到字典 ----> 转成josn字符串 ----> json字符串转成二进制 ----> 计算json二进制的长度 ----> struct打包成四个字节的二进制数据
先发送4个长度的二进制数据 ----> json二进制数据 ----> 总的数据
(1)客户端
先接收收到4个长度的二进制数据 ----> 转码(json二进制数据的长度)----> 继续从通道里面取出json二进制长度的二进制数据 ----> 转码(总数据的长度)----> 获取总的数据
先接收4长度的struct二进制数据 ----> josn二进制数据 ----> 总数据
【六】struct模块如何使用
【1】format参数用于指定打包和解包数据的格式
-
整数类型:
b
:有符号字节(signed char)B
:无符号字节(unsigned char)h
:有符号短整数(signed short)H
:无符号短整数(unsigned short)i
:有符号整数(signed int)I
:无符号整数(unsigned int)l
:有符号长整数(signed long)L
:无符号长整数(unsigned long)q
:有符号长长整数(signed long long)Q
:无符号长长整数(unsigned long long)
-
浮点类型:
f
:单精度浮点数(float)d
:双精度浮点数(double)
-
字符串类型:
s
:固定长度的字符串,后面跟上字符串长度。例如,10s
表示长度为10的字符串。p
:与s
类似,但会自动在字符串后面添加空字节。例如,10p
表示长度为10的字符串,末尾会自动添加空字节。
-
其他类型:
?
:布尔值(bool)x
:占位符,用于对齐数据
在使用format参数时,可以将多个格式代码组合在一起。例如,'ihi'
表示有符号整数、有符号短整数、有符号整数的顺序。
需要注意的是,在使用struct模块时,打包和解包数据的格式必须一致,否则会导致数据解析错误。
【2】使用方法
import struct# 打包数据
data = struct.pack('10s', b'123')
print(f"打包数据 data: {data}")# 解包数据
unpacked_data = struct.unpack('10s', data)
print(f"解包数据 data: {unpacked_data}")
# 打包数据 data: b'123\x00\x00\x00\x00\x00\x00\x00'
# 解包数据 data: (b'123\x00\x00\x00\x00\x00\x00\x00',)