软件开发架构
客户端+服务端
- 服务端:24小时提供服务
- 客户端:寻找服务
C/S架构
Client:客户端
server:服务端
优点:软件的使用稳定,可以节省网络资源
缺点:
- 若用户想在同一个设备上使用多个软件,必须下载多个客户端
- 软件的每一次更新,客户端也必须重新下载更新
C/S架构的软件
例如:电脑上的QQ,pycharm,手机端的微信,王者荣耀等
B/S架构
Browser:浏览器(客户端)
Server:服务器
优点
以浏览器充当客户端,无需用户下载多个软件,也无需用户下载更新软件版本,直接在浏览器访问需要使用的软件
缺点
消耗网络资源过大,当网络不稳定时,软件使用也会不稳定
B/S架构的软件
例如在浏览器上输入某个域名的地址
网络编程、并发编程、数据库开发可以开发C/S架构的软件(仿优酷系统)
前端html、css、js、web框架(网络编程、并发编程)可以开发B/S架构的软件(BBS系统)
网络编程
要实现远程通信必须具备:
- 物理连接介质:比如网卡
- 互联网协议:计算机沟通的介质,就好比人类交流的语言
互联网协议/OSI七层协议
互联网协议又称为网络七层协议/OSI七层协议,ISO是一个世界组织
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理连接层
传输层
TVP//UDP协议,都是基于端口工作的
端口号:标识电脑上某一个应用程序
端口号范围:0-65535
注意:
- 操作系统中,一般0-1024的段都被默认使用了(不要动)
- 尽量使用8000之后端口
开发中常用软件的端口号
- mysql:3306
- mongodb:8000
- Django:8080
- Flask:5000
- Redis:6379
若想服务端和客户端进行通信,必须要建立连接,产生双向通道(两条管道)
- 一条是客户端往服务端发送消息
- 一条是客户端往服务端发送消息
总结
- ip:用于唯一表示某一台计算机的位置
- port:端口用于确认计算机上的一个应用程序
ip+port:世界上某一台电脑上的一个应用软件
TCP协议的工作原理
TCP是一个流式协议
三次握手,四次挥手
三次握手键连接
建立双向通道
- Listen:监听
- established:确认请求建立连接
发送数据
客户端往服务端发送数据,数据存放在内存中,需要服务端确认收到,数据才会在内存中释放,否则,会隔一段时间发送一次,让服务端返回确认收到
在一段时间内,如果服务端还是不返回确认收到,则取消发送,并释放内存中的数据
四次挥手断连接
TIME_WAIT:时间等待
网络层
IP地址:用于表示计算机(IP地址)
IP:点分十进制
最小值:0.0.0.0
最大值:255.255.255.255
IPV4:
一开始用电脑的人不多,所以出现了IPV4的协议版本
IPV6
后来用的人多了,出现了IPV6,包括IPV4
本机IP
- 回环地址:127.0.0.1(localhost)
数据链路层
数据链路层的‘以太网协议,专门用于处理基于电信号发送的数据
以太网协议
- 规定好电信号数据的分组方式
- 每一台连接网线的电脑都必须要由一块“网卡”
- 网卡是由不同厂商生产的
- 每块网卡都会有世界上独一无二的12为编号
- 前六位:厂商号
- 后六位:流水号
交换机
可以让多台电脑连接到一起
基于以太网协议发送数据
特点:广播,单播
弊端:广播风暴,不能跨局域网通信
互联网
让局域网之间可以通信
物理连接层
- 基于电信号发送二进制的数据
socket
什么是socket
socket是一个模块,可以写一套C/S架构的套接字
为什么用socket
socket套接字会封装好各层协议的工作
- 好处
- 可以节省开发成本
如何使用
单次通信
# 服务端.py import socket # 默认指定TCP协议 server = socket.socket() # 相当于买手机 # 插卡 sever.bind( ('127.0.0.1',9527) ) # IP+port 元组 # 相当于开机,等待接听 sever.listen(5) # 半连接池 # 监听是否有消息 # conn相当于服务端往客户端挖的管道 conn,addr = sever.accept() # 返回的(sock,addr) print(addr) # 接受客户端的消息 data = conn.recv(1024) # 可以接受1024字节数据 # data = conn.recv(1024).decode('utf-8') print(data) conn.send(b'hi') # 相当于挂掉电话 conn.close() # 相当于关机 sever.close
# 客户端.py import socket # 买手机 client = socket.socket() # 往服务端拨号 # client详单与客户端往服务端挖的管道 client.connect( ('127.0.0.1',9527) ) # ip+port 寻找服务端 # 客户端向服务端说话 client.send(b'hello') # client('你好'.encode('utf-8')) data = client.recv(1024) # data = client.recv(1024).decode('utf8') print(date) # 关闭连接 client.close()
注意:客户端与服务端必须遵循“一端send,另一端recv”不能两端同时send或recv
循环通信
# 服务端.py import socket server = socket.socket() # 相当于买手机 sever.bind( ('127.0.0.1',9527) ) sever.listen(5) # 半连接池 conn,addr = sever.accept() # 返回的(sock,addr) print(addr) while True: # 接收客户端发送过来的消息 data = conn.recv(1024) print(data) if data = 'q': break # 让服务端输入发送给客户端的消息 send_msg = input('服务端-->客户端').encode(utf-8) conn.send(send_msg) conn.close() sever.close
# 客户端.py import socket client = socket.socket() client.connect( ('127.0.0.1',9527) ) # ip+port 寻找服务端 while True: send_msg= input('客户端--》服务端') # 服务端发送给客户端的数据 client.send(send_msg.encode('utf-8')) # 服务端返回的数据 client.recv(1024).decode('utf-8') print(1024) client.close()
服务端连接多个客户端
# 服务端 import socket server = socket.socket() server.bind( ('127.0.0.1', 8888) ) server.listen(5) # 半连接池,可以“等待5个用户接受服务” while True: # 等待客户端连接过来 conn, addr = server.accept() print(addr) # 循环接收客户端数据 while True: try: data = conn.recv(1024).decode('utf-8') print(data) # mac和linux系统bug: b'' if len(data) == 0: continue if data == 'q': break conn.send(data.encode('utf-8')) except Exception as e: print(e) break conn.close()
# 客户端 import socket client = socket.socket() client.connect( ('127.0.0.1', 8888) ) while True: send_msg = input('>>>:') client.send(send_msg.encode('utf-8')) if send_msg == 'q': break data = client.recv(1024).decode('utf-8') print(data) client.close()