python三十五期---TCP与UDP协议,socket模块基本使用
昨日内容回顾
-
软件开发架构
1.C/S架构 客户端、服务端 2.B/S架构 浏览器、服务器 B/S本质也是C/S架构
-
网络编程前戏
基于网络实现数据交互 计算机之间要想实现数据交互必须有物理链接介质(前提)
-
OSI七层协议
应用层、表示层、会话层、传输层、网络层、数据链路层、物理链接层 应用层、传输层、网络层、数据链路层、物理链接层 (核心) 应用层、传输层、网络层、网络接口层
1.物理链接层
建立物理链接介质
2.数据链路层
规定了电信号的分组方式
以太网协议
3.网络层
IP协议:规定了接入互联网的计算机都必须有一个ip地址
IP地址:
IPV4
点分十进制 数量有限
IPV6
能够表示地球上的每一粒沙子
特征:IP能够标识出地球上独一无二的一台接入互联网的计算机
"""
ARP协议:能够根据IP地址动态解析到一个MAC地址
谁正在使用某个IP地址 我们就可以根据IP地址动态解析到使用者的MAC地址
"""
4.传输层
PORT协议:计算机通过端口号管理正在运行的诸多应用程序
端口号:0-65535
特征:可以指定也可以动态分配
能够标识出计算机上独一无二的一个应用程序
* 各种协议
```python
1.以太网协议
规定了计算机在出厂的时候都必须有一块网卡 上面有一串数字
该数字就是计算机的物理地址>>>:MAC地址(身份证号码)
2.IP地址:
IPV4
点分十进制 数量有限
IPV6
能够表示地球上的每一粒沙子
特征:IP能够标识出地球上独一无二的一台接入互联网的计算机
"""
ARP协议:能够根据IP地址动态解析到一个MAC地址
谁正在使用某个IP地址 我们就可以根据IP地址动态解析到使用者的MAC地址
"""
3.端口号:0-65535
特征:可以指定也可以动态分配
能够标识出计算机上独一无二的一个应用程序
-
专业名词解释
1.交换机 2.广播 3.单播 4.广播风暴 5.局域网、广域网、互联网 6.路由器 7.域名就是URL就是网址 8.域名解析(DNS服务器) 域名 >>>>>> ip:port
今日内容概要
- 传输层之TCP与UDP协议
- 应用层
- socket模块简介
- socket模块基本使用
- 代码优化处理
- socket黏包问题
- 黏包问题的解决方案
今日内容详细
.
.
socket模块
如果我们需要编写基于网络进行数据交互的程序
意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)
socket类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口
-----------------------------------------
理解socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,
Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,
一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
-----------------------------------------
Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,
一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
-----------------------------------------
socket也叫套接字
基于文件类型的套接字家族(单机)
AF_UNIX
-------------
基于网络类型的套接字家族(联网)
AF_INET
-----------------------------------------
在这里主要学习利用socket完成TCP/IP通讯,首先需要生成两个对象,
一个是客户端(client),一个是服务端(sever)。
.
.
.
.
.
socket代码简介
socket 插座;窝(n);使装入插座(v) 也有端口的意思!!!
bind 捆绑, 捆扎 (v)
listen
.
.
.
.
暂时只要想实现网络通信就要使用socket模块!!!
## 先建立服务端代码
import socket
# 1. 产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket()
# 括号内不写参数 默认就是TCP协议
# family=AF_INET基于网络的套接字 type=SOCK_STREAM流式协议即TCP
# 2. 绑定要连接的端口 (服务端ip地址,服务端的端口号) 元祖形式(ip地址,端口号)
server.bind(('127.0.0.1', 8080))
# 127.0.0.1为本地回环地址 只有自己的电脑可以访问,
# 如果没有申请公ip,只能在局域网实现让别的客户端访问该服务端的操作!!
# 3. 设置监听端口的状态,设立半连接池
server.listen(5) # 有5个空位
# 4. 等待客户连接
sock, addr = server.accept() #该方法有两个返回值 return sock, addr 三次握手!
print(sock, addr) # sock就是双向通道, 注意此处addr是客户端的IP地址加端口!!!
# 5. 接收客端发来的消息
data = sock.recv(1024) # 通过双向通道接收客户端发送过来的消息,只接收1024字节,剩下的就不要了!
print(data.decode('utf8'))
# 6. 给客户端发送消息 注意消息必须是bytes类型
sock.send('尊敬的客人 您说什么就是什么 一切按照您的要求来'.encode('utf8'))
# 7. 关闭双向通道
sock.close() # 四次挥手???
# 8. 关闭服务端
server.close() # 店倒闭了
# 这样服务端就写好了,运行该程序后,会卡在等待客户连接的状态!!!
# 服务端代码必须要先运行起来,才能再去运行客户端代码!!!
-----------------------------------------------
.
.
.
再建立客户端代码!!!!!
## 再建立客户端代码!!
import socket
# 1.生成socket对象指定类型和协议
client = socket.socket()
# 2.通过服务端的地址链接服务端!!!!!!
client.connect(('127.0.0.1', 8080)) # 三次握手
# 3.直接给服务端发送消息 ,客户端先发消息,服务端接收到消息后再发送消息给客户端,客户端再接收消息!!!
client.send('大爷有钱 把你们店最好的给我叫出来'.encode('utf8'))
# 4.接收服务端发送过来的消息
data = client.recv(1024)
print(data.decode('utf8'))
# 5.断开与服务端的链接
client.close()
------------------------------
整体的一个思路:
就是服务端代码先跑起来,卡在等待客户连接的状态
客户端代码跑起来,走到connnect连接代码后,向服务端发送连接请求
服务端接受连接请求后,拿到客户端的ip地址与接口,还有双向通道
客户端开始给服务端发送消息
服务端接收消息,并给客户端回消息
客户端接收到服务端回的消息后,断开与服务端的连接
服务端关闭双向通道,断开与服务端连接
------------------------------------
网络数据交互的一个雏形!!!!!!
很多代码和框架都是由这几行代码演变而来的!!!!!!!!
是所有牛逼的框架的底层的基础代码!!!!!!
.
.
.
.
.
.
.
.
.
.
代码优化
1.聊天内容自定义
针对消息采用input获取
--------------------------------------
2.让聊天循环起来
将聊天的部分用循环包起来
---------------------------------------
当客户端异常断开时,如何让服务端继续正常运行???windows系统服务端会直接报错,
苹果电脑会出现重复发空消息,好多次后会出现报错的现象!!!
怎么办?
应该要能自动识别出该报错信息,
并且应该要让代码能正常回退到accept那边等待新的对象连接请求!!!
当服务端接收到空消息后,说明此时客户端异常断开或者代码终止运行了,
或者客户端就什么都没发,直接按了一个回车了。
---------------------------------------
3.用户输入的消息不能为空!!!!用户的输入的为空,服务端sock.recv(1024)收不到消息后,
就会卡在这了不走了,这时候客户端与服务端两边代码都走到了recv这了,这个时候就尬住了!!!!
本质其实是两边不能都是recv或者send!!!!!!
一定是一方收一方发!!!!!!!!
---------------------------------------
4.苹果电脑:服务端多次重启可能会报错
Address already in use 主要是mac电脑会报
方式1:改端口号
方式2:
from socket import SOL_SOCKET,SO_REUSEADDR
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
---------------------------------------
5.当客户端异常断开的情况下 如何让服务端继续服务其他客人???
windows服务端会直接报错
mac服务端会有一段时间反复接收空消息延迟报错
异常处理、空消息判断!!!!
---------------------------------------
.
.
.
.
.
没优化前代码
---------------------------------------------------
服务端
import socket
server = socket.socket()
# 2.通过服务端的地址链接服务端!!!!!!
server.bind(('127.0.0.1', 8080))
server.listen(5)
sock, addr = server.accept()
# 客户端发送连接请求,服务端接收连接请求,获取双向通道,并拿到客户端的ip地址与端口号
data = sock.recv(1024)
print(f'来自于客户端{addr}的消息>>>>:', data.decode('utf8'))
msg = input('请输入发送给客户端的而消息>>:').strip()
sock.send(msg.encode('utf8'))
sock.close()
----------------------------------------------------
客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080)) # 连接的服务端地址!!!
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))
.
.
.
.
.
.
.
.
让聊天循环起来-------优化后代码
-----------------------------------------------------
服务端
import socket
# 1.产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket()
# 2.通过服务端的地址链接服务端!!!!!!# 2.绑定要监控的界面((服务端ip地址,服务端的端口号))
server.bind(('127.0.0.1', 8080))
server.listen(5) # 3.监听端口状态,设立半连接池
sock, addr = server.accept() # 三次握手建立连接
# 客户端发送连接请求,服务端接收连接请求,获取双向通道,并拿到客户端的ip地址与端口号
while True:
data = sock.recv(1024) # 通过双向通道接收客户端发送过来的消息,如果客户端不发,代码就卡在这边,所以不会出现死循环!!
print(f'来自于客户端{addr}的消息>>>>:', data.decode('utf8'))
msg = input('请输入发送给客户端的而消息>>:').strip()
sock.send(msg.encode('utf8')) # 通过双向通道发送消息给客户端!!!
# sock.close() # 这行不用写了,操作结束,操作系统回自动回收双向通道!!!
-------------------------------------
客户端
import socket
client = socket.socket() # 1.生成socket对象指定类型和协议
client.connect(('127.0.0.1', 8080)) # 2.通过服务端的地址链接服务端!!!
# 服务端一旦接受,这边就拿到双向通道了!!就可以和服务端来回的聊天了!!!!!
while True:
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
client.send(msg.encode('utf8')) # 注意send发送的信息必须是bytes类型二进制数据!!!
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))
# 当客户端终止程序运行后,或者当客户端异常断开时,服务端会报错!!!!
-------------------------------------
.
.
.
.
.
服务端最终优化后!!!!
import socket
from socket import SOL_SOCKET, SO_REUSEADDR # 针对苹果电脑,服务端多次重启可能会报错的问题,要导入两个模块!!!!!!
# 1.产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket()
# 2.通过服务端的地址链接服务端!!!!!!# 2.绑定要监控的界面((服务端ip地址,服务端的端口号))
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 针对苹果电脑的,加这行代码!!!!!!
server.bind(('127.0.0.1', 8080))
server.listen(5) # 3.监听端口状态,设立半连接池
while True:
sock, addr = server.accept() # 三次握手建立连接
# 客户端发送连接请求,服务端接收连接请求,获取双向通道,并拿到客户端的ip地址与端口号
while True: # 聊天的过程可能出现报错的情况,所以加个异常捕获
try:
data = sock.recv(1024) # 通过双向通道接收客户端发送过来的消息,
# 如果客户端不发,代码就卡在这边,所以不会出现死循环!!
if data == 0:
# 如果监测到收到的消息为空后,跳出小循环,到大循环里面去,等待用户发送连接请求!!!
break
print(f'来自于客户端{addr}的消息>>>>:', data.decode('utf8'))
msg = input('请输入发送给客户端的而消息(不能发空消息!!)>>:').strip()
# 并且服务端发消息也不能为空不然还是会尬住了!!!
# 但是服务端是一个固定的程序,不是一个人!!!
sock.send(msg.encode('utf8')) # 通过双向通道发送消息给客户端!!!
except Exception: # 一旦监测到报错信息,也break结束的掉小循环!!
break
# sock.close() # 这行不用写了,操作结束,操作系统回自动回收双向通道!!!
# 微信两个人聊天,不是客户端与服务端交流,而是两个聊天的人都是客户端,
# 是1个人通过客户端把消息发给微信的服务端,然后服务端再把消息传给对应的另一个客户端!!!
# 微信的服务端作为一个中转站!!!
.
.
.
.
.
.
.
.
import socket
client = socket.socket() # 1.生成socket对象指定类型和协议
client.connect(('127.0.0.1', 8080)) # 2.通过服务端的地址链接服务端!!!
# 服务端一旦接受,这边就拿到双向通道了!!就可以和服务端来回的聊天了!!!!!
while True:
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
# 加个判断,这样就可以避免客户端发空消息的情况了!!!,两边就不会尬住了!!!
# 并且服务端发消息也不能为空不然还是会尬住了!!!
if not len(msg):
print('不能发送空消息!!')
continue
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))
.
.
.
.
.
.
.
半连接池的概念
server.listen(5) # 半连接池
半连接池相当于建立了一个缓冲地带,除第一个外,还有5个客户端可以与服务端连接,
后面的客户端就连接不上了。
注意:另外五个虽然能连接,但是服务端一次只能服务一个客户端,所以另外5个人虽然能连接,
但并不能与服务端进行收发消息交流,只能在第一个客户端断开连接后,
下一个客户端才能与服务端进行信息的交流!!!!!!
当有多个客户端来链接的情况下 我们可以设置连接的客户端的等待数量(不考虑并发问题)
假设服务端只有一个人的情况下
在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可
.
.
.
.
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY