OSI七层协议,软件架构,socket编程,TCP和UDP协议
OSI七层协议(规则)
# 七层划分为:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层
# 五层划分为:物理层,数据链路层,网络层,传输层,会话层,应用层
传输层:TCP协议和UDP协议
网络层(路由器...)
会话层(淘宝登录...)
应用层(微信,浏览器...)
软件架构
C/S : client:客户端 server => 服务端
B/S : browser:浏览器 server => 服务端
# 本质:B/S架构也是C/S架构
TCP和UDP协议(传输层)
TCP协议的特点:
1. 数据可靠传输(TCP协议的三次握手和四次挥手(如下图))
2. 速度相对于UDP协议较慢
UDP协议的特点:
1. 数据不可靠
2. 速度相对于TCP协议较快
tcp三次握手和四次挥手
客户端向服务端主动发起连接请求,服务端收到请求响应客户端并发起对客服端端连接请求,
客户端告诉服务端收到请求,此时才能百分百确认建立连接。
为什么建立连接是三次握手,关闭连接确是四次挥手
建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文
里发送给客户端。而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还
能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给
对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从
而导致多了一次。(客户端发起断开连接请求,服务端不能直接断开连接,因为可能还有数据没有完全
传输完毕,等这次数据传输完毕,服务端再发一次请求告诉服务端这次数据传输完了,客户端告诉服
务端收到请求,此时才彻底断开连接)
socket抽象层(不属于OSI七层协议)
# 本机的IP地址:127.0.0.1 (win+R ——>cmd——>回车——>ipconfig——>IRv4地址/IRv6地址)
192.168开头的是局域网的ip地址(公司网络),我们一般用的是广域网
socket抽象层:就是一个个的对外访问的接口(浅显的理解就是函数,然后调用函数)
在传输层当中传输的数据形式都是二进制
# 什么是Socket呢?
我们经常把**Socket翻译为套接字**,Socket是在应用层和传输层之间的一个抽象层(人为定义),它把 TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用
套接字工作流程
域名跟ip进行了绑定——>域名解析
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),
调用accept阻塞,等待客户端连接接收数据。在这时如果有个客户端初始化一个Socket,然后连接服
务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务
端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,**read在python中是receive**
最后关闭连接,一次交互结束
基于TCP协议的套接字(socket)编程
**************************************服务端****************************************
import socket
# 1. 实例化socket对象
# 参数不传递默认代表是TCP协议
server = socket.socket(type=socket.SOCK_STREAM) # socket 模块名.类名
# 2. 绑定
server.bind(('127.0.0.1', 8001))
# 8001——>端口(prot),服务器端要用 bind() 函数将套接字与特定的 IP 地址和端口绑定起来
# 3. 监听, 括号中是半连接池,(5)相当于服务端只服务5个人,第6个人来就报错
server.listen(5)
# 4. 接收客户端发来的信息
print("正在等待客户端发来的消息:")
# sock:当次链接对象,addr:客户端的地址, ip+port端口
sock, addr = server.accept()
# 5. 拿到数据, 单位最多接收1024个字节的数据,接收字节类型Byte类型(可能出现粘包现象)
data = sock.recv(1024)
print(data)
# 6. 发送客户端的数据
sock.send(data.upper())
# 7. 断开链接
sock.close()
# 8.
server.close()
**************************************客户端******************************************
import socket
client = socket.socket()
client.connect(('127.0.0.1',8001))
# 向服务端发送数据
client.send(b'hello baby') # 通过b前缀将字符串转换成 bytes
# 接收服务端发来的数据
data = client.recv(1024)
print(data)
client.close()
# 客户端只能发送一次就断开,服务端只接受一个客户端服务完立马就断了
加上链接循环(服务端能够多次接收客户端发来的请求)
**************************************服务端****************************************
import socket
# 1. 实例化socket对象
# 参数不传递默认代表是TCP协议
server = socket.socket(type=socket.SOCK_STREAM)
# 2. 绑定
server.bind(('127.0.0.1', 8001))
# 3. 监听, 括号中是半连接池
server.listen(5)
# 4. 接收客户端发来的信息
print("正在等待客户端发来的消息:")
while True:
# sock:当次链接对象,addr:客户端的地址, ip+port
sock, addr = server.accept()
# 5. 拿到数据, 一次最多接收1024个字节的数
data = sock.recv(1024)
print(data)
# 6. 发送客户端的数据
sock.send(data.upper())
# 7. 断开链接
sock.close()
# 8.
server.close()
**************************************客户端****************************************
import socket
client = socket.socket()
client.connect(('127.0.0.1',8001))
# 向服务端发送数据
client.send(b'hello baby')
# 接收服务端发来的数据
data = client.recv(1024)
print(data)
client.close()
实现通信循环
**************************************服务端****************************************
import socket
# 1. 实例化socket对象
# 参数不传递默认代表是TCP协议 # SOCK_STREAM : tcp协议的服务端
server = socket.socket(type=socket.SOCK_STREAM)
# 2. 绑定
server.bind(('127.0.0.1', 8002))
# 3. 监听, 括号中是半连接池
server.listen(5)
# 4. 接收客户端发来的信息
print("正在等待客户端发来的消息:")
while True:
# **sock:当次链接对象**,addr:客户端的地址, ip+port
sock, addr = server.accept()
while True:
# 5. 拿到数据, 一次最多接收1024个字节的数据
try:
data = sock.recv(1024)
print(data)
# 6. 发送客户端的数据
sock.send(data.upper())
except as e:
print(e)
break
# 7. 断开链接
sock.close()
# 8.
server.close()
**************************************客户端****************************************
import socket
client = socket.socket()
client.connect(('127.0.0.1',8002))
while True:
# 向服务端发送数据
input_data = input('请输入数据:').strip()
client.send(input_data.encode('utf-8')) # # 通过encode将字符串转换成 bytes
# 接收服务端发来的数据
data = client.recv(1024)
print(data)
client.close()
基于UDP协议的套接字编程
**************************************服务端****************************************
import socket
# SOCK_DGRAM :udp协议的服务端
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 数据报协议-》UDP
server.bind(('127.0.0.1', 8080)) #绑定
while True:
data, client_addr = server.recvfrom(1024) # client_addr客户端地址
print('===>', data, client_addr)
server.sendto(data.upper(), client_addr)
server.close()
**************************************客户端****************************************
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 数据报协议-》UDP
while True:
msg = input('>>: ').strip() # msg=''
client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
data, server_addr = client.recvfrom(1024)
print(data)
client.close()