一、传输层之——TCP与UDP协议
协议很多种,都是为了规定数据交互的方式,数据传输能够遵循的协议有很多 TCP和UDP只是比较常见的两个
1.TCP协议
一种可靠的基于(面向)连接的协议,协议规则是通信的双方要有彼此的通信通道
为何可靠>>>:C端或者B端在传给S端数据时,根据这个TCP协议写的网络交互程序是先将发送数据端要发送的数据复制一份,传输给S端,S端收到后反馈东西确实完整收到后,C端要传的数据才会在内存中被删除掉,所以接收端是一定能收到发送端发送的数据的,这就是可靠
- 补充:
- TCP协议又叫老好人协议,只要来个请求,不管是是不是攻击者还是正常用户,有请求我都给你办事
2.TCP协议之——三次握手(意为建立连接通道)
PS:其实有四次,因为发送端发请求过来,接收端收到,收到后接受端发送了一个确认信息给发送端,同时接收端也发请求给原发送端,到这里就已经有三步骤了,不过第二步和第三步可以合二为一,所以才有三次握手
图解:
SYN是发送一个基于TCP协议的包,包有一些规范的格式,格式里有标志位,当服务端收到的TCP包内的标志位为1就知道这是一个请求建立连接的包。
ACK是一个基于TCP协议的确认包
SYN后面跟着的seq相当于序列号,是防止被人串改,也是能表示谁是谁,我要回复谁(回复就基于序列号+1)
注意单词:
SYN_SENT : 请求建立连接状态
SYN_RCVD :建立连接状态
ESTABLISHED:连接已经建立完成,可以传数据了
# 简单理解
# ________________________________________
1)Client:小李子!小李子!是我,能听到我说话吗?
2)Server:我可以听到你说话,你能听到我说话吗?
3)Client:我这边听你说话也没问题,那咱们可以开始通信了
-
补充:
-
洪水攻击
搞很多个客户端请求服务器,造成服务器堵塞,服务器会被
搞瘫痪,假客户端有假IP,发完请求就跑路了,这样服务端
就不停的处于SYN_RCVD情况下(所以看到服务端长期处
于该状态就说明有可能在遭受洪水攻击)
-
3.TCP协议之——四次挥手(意为断开连接通道)
图解:
FIN是发送一个标识位
ACK依旧是一个基于TCP协议的确认包
后面跟着的seq依旧相当于序列号,是防止被人串改,也是能表示谁是谁,我要回复谁(回复就基于序列号+1)
注意单词:
TIME_WAIT : 等待确认数据是否发完状态,正因为这个状态
存在,所以四次挥手不能省一步!!!
当服务端大量处于该状态时,意味着服务端正在经历高并发
# 简单理解 (但是注意,一般是客户端先提出断开请求)
# ________________________________________
1)Client:我所有东西都说完了,我想断我到你的通道
2)Server:我已经全部听到了,你到我的通道已经断掉,但是婷婷,我还没说完
3)Server:好了,我已经说完了,我也想断我到你的通道
4)Client:好的,你到我的通道已经断开,我们的通讯结束
4.UDP协议
不可靠协议,不管接收方收没收到,就硬传就完事,简单粗暴,效率高,但是不够安全,一般注重用户数据的软件不会使用该协议作为底层
二、应用层
主要取决于程序员自己采用什么策略与协议
常见的协议有:HTTP、 HTTPS、FTP …
三、socket模块(自带的模块)
俗称套接字,类似一个操作系统,极大的简化用户操作osi四层协议
1.格式
Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
- family: 套接字家族可以使AF_UNIX或者AF_INET
AF_UNIX:基于文件类型的套接字家族
AF_INET:基于网络类型的套接字家族——常用
- type: 套接字类型可以根据是面向连接的还是非连接分为`SOCK_STREAM`或`SOCK_DGRAM`
TCP UDP
- protocol: 一般不填默认为0.
2.简单写一个服务端、用户端
1.服务端
# 服务端
import socket
from socket import SOL_SOCKET, SO_REUSEADDR # 兼容苹果的一个报错重复连接问题
# 创建一个socket 对象
server = socket.socket()
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 兼容苹果的一个报错重复连接问题
# 绑定一个固定的地址(ip\port)
# 127.0.0.1 为本地回环地址(只允许自己的机器访问)
host = '127.0.0.1'
PORT = 11111
server.bind((host, PORT))
# 半连接池,限制最大访问量,能正常缓冲6个用户 开始监听
server.listen(5)
# 准备就绪 等待客户端 来访问(开业,等待接客)
# 添加循环 让服务端 每次结束客户端连接接触都能回归为等待访问的状态
print(f'服务端启动成功,地址来自>>>{host}, PORT端口为>>>{PORT}')
while True:
sock, address = server.accept()
# sock 是双向通道 address是客户端地址
print(sock, address)
# 数据交互
# 朝客户端发送数据
# 添加循环 让服务端 能够自定义返回的数据
while True:
try:
sent_data = input('请输入发送的数据>>>').strip()
if len(sent_data) == 0:
print('消息不能为空')
continue
sock.send(sent_data.encode('utf8')) # 发送给客户端
# 接收 客户端发送的数据 长度自定
data = sock.recv(1024)
data = str(data, 'utf')
print(data)
# 当客户端断开过后 捕获异常
except Exception:
break
#
# 断开连接
sock.close()
2.客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 11111)) # 连接要访问的地址
a = client.recv(1024) # 接收 服务端发送的数据 长度自定
print(a.decode('utf8'))
while True:
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
if len(msg) == 0:
print('不能发送空消息')
continue
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))
标签:协议,UDP,socket,TCP,发送,传输层,服务端,客户端
From: https://www.cnblogs.com/wznn125ml/p/16897400.html