OSI七层协议:
七层划分为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
五层划分为:应用层、传输层、网络层、数据链路层、物理层。
传输层:TCP协议和UDP协议
软件架构:C/S : client server => 服务端
B/S : browser:浏览器 server => 服务端
本质:B/S架构也是C/S架构
TCP和UDP协议
TCP协议的特点:
1. 数据可靠传输
2. 速度相对于UDP协议较慢
UDP协议的特点:
1. 数据不可靠
2. 速度相对于TCP协议较快
TCP协议的三次握手和四次挥手
本机的IP地址:127.0.0.1
socket抽象层:就是一个个的对外访问的接口
socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
我们经常把Socket翻译为套接字,Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用
套接字分类
- 基于文件类型的套接字家族:AF_UNIX
- 基于网络类型的套接字家族:AF_INE
套接字工作流程
套接字函数
一、服务端套接字函数
- s.bind() 绑定(主机,端口号)到套接字
- s.listen() 开始TCP监听
- s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
二、客户端套接字函数
- s.connect() 主动初始化TCP服务器连接
- s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
三、公共用途的套接字函数
- s.recv() 接收TCP数据
- s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
- s.sendall() 发送完整的TCP数据(本质就是循环调用
- send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
- s.recvfrom() 接收UDP数据
- s.sendto() 发送UDP数据
- s.getpeername() 连接到当前套接字的远端的地址
- s.getsockname() 当前套接字的地址
- s.getsockopt() 返回指定套接字的参数
- s.setsockopt() 设置指定套接字的参数
- s.close() 关闭套接字
四、面向锁的套接字方法
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
五、面向文件的套接字的函数
- s.fileno() 套接字的文件描述符
- s.makefile() 创建一个与该套接字相关的文件
- 六、基于tcp的套接字
-
服务端 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("正在等待客户端发来的消息:") # 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协议 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 Exception 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(b‘hello baby‘) client.send(input_data.encode(‘utf-8‘)) # 接收服务端发来的数据 data = client.recv(1024) print(data) client.close()
- 七、基于udp的套接字
-
服务端 import socket # SOCK_STREAM : tcp协议的服务端 # 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) 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()