C/S B/S 架构python
C:client端,客户端 B:Browser,浏览器 S:server,服务端 C/S 客户端与服务器之间的架构:QQ,微信,游戏,APP等都属于C/S架构 优势:安全性高,个性化设置,功能全面,响应速度快。 缺点:开发成本高,维护成本高。(基于APP),面向的客户固定 B/S:浏览器与服务器之间的架构:它属于C/S架构,最近几年比较流行的特殊的C/S架构 优势:开发维护成本低,面向用户普遍 缺点:安全性相对低,响应速度相对慢,个性化的设置单一
互联网通讯的原理shell
osi 七层协议(tcp/ip五层协议或tcp/ip四层协议)编程
七层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层浏览器
五层:应用层(应,表,会),传输层,网络层,数据链路层,物理层安全
四层:应用层(应,表,会),传输层,网络层,网络接口层(数,物)服务器
每层运行常见的物理设备:微信
传输层:四层交换机,四层的路由器网络
网络层:路由器,三层交换机架构
数据链路层:网桥,以太网交换机,网卡socket
物理层:中继器,集线器,双绞线
下面咱们来倒着分析一下五层协议
物理层
一系列的物理链接介质:网线,光纤,电缆,无线网络等
发送的数据是0101011100形式的比特数据流,主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0
数据链路层:遵循以太网协议
数据链路层的由来:单纯的电信号0和1没有任何意义,必须规定电信号多少位一组,每组表明什么意思
数据链路层的功能:定义了电信号的分组方式
以太网协议(ethernet):统一了电信号的分组方式
Ethernet规定:
Ethernet规定:一组电信号构成一个数据报,叫作“帧” 每一数据帧分红:报头 head 和数据 data 两部分 head 包含:(固定18个字节) 发送者/源地址,6个字节 接收者/目标地址,6个字节 数据类型,6个字节 data 包含:(最短46个字节,最长1500字节) 数据包的具体内容 head 长度 + data 长度 = 最短64字节,最长1518个字节,超过最大限制就分片发送 MAC地址:head 中包含的源地址和目标地址的由来,ethernet 规定接入 internet 的设备都必须具有网卡,发送端和接收端的地址即是指网卡地址,即MAC地址 MAC地址:每块网卡出厂时都被烧制上一个世界惟一的MAC地址,长度为48位2进制,一般由12位16进制数表示(前六位是厂商编号,后六位是流水线号) 广播: 计算机最原始的通讯方式就是吼. 数据的分组(源地址目标地址) + 广播: 理论上个人计算机就能够通讯了.可是效率过低,每台计算机都须要接收广播的消息,查看是不是给本身的数据.比广播风暴还要严重. 因此: 广播它是有范围的,在同一子网,局域网内是经过广播的方式,发消息.
网络层:遵循IP协议
网络层由来:是为了肯定目标计算机在局域网内的位置
网络层功能:引入一套新的地址用来区分不一样的广播域/子网,这套地址即网络地址
IP协议:规定网络地址的协议叫 IP 协议,它定义的地址称之为 ip 地址,普遍采用的v4版本即ipv4,它规定网络地址由32位2进制表示
一个ip地址一般写为四段十进制数,如:172.16.10.1
ip地址范围:0.0.0.0 - 255.255.255.255
ip地址分红两个部分:
网络部分:标识子网
主机部分:标识主机
注意:单纯的ip地址段只是标识了ip地址的种类,从网络部分或主机部分都没法辨识一个ip所处的子网
例:172.16.10.1与172.16.10.2并不能肯定两者处于同一子网
子网掩码:
所谓”子网掩码”,就是表示子网络特征的一个参数。它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部分所有为1,主机部分所有为0。好比,IP地址172.16.10.1,若是已知网络部分是前24位,主机部分是后8位,那么子网络掩码就是11111111.11111111.11111111.00000000,写成十进制就是255.255.255.0。 知道”子网掩码”,咱们就能判断,任意两个IP地址是否处在同一个子网络。方法是将两个IP地址与子网掩码分别进行AND运算(两个数位都为1,运算结果为1,不然为0),而后比较结果是否相同,若是是的话,就代表它们在同一个子网络中,不然就不是。 好比,已知IP地址172.16.10.1和172.16.10.2的子网掩码都是255.255.255.0,请问它们是否在同一个子网络?二者与子网掩码分别进行AND运算, 172.16.10.1:10101100.00010000.00001010.000000001 255255.255.255.0:11111111.11111111.11111111.00000000 AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0 172.16.10.2:10101100.00010000.00001010.000000010 255255.255.255.0:11111111.11111111.11111111.00000000 AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0 结果都是172.16.10.0,所以它们在同一个子网络。 总结一下,IP协议的做用主要有两个,一个是为每一台计算机分配IP地址,另外一个是肯定哪些地址在同一个子网络。
ip数据包
ip数据包也分为head和data部分,无须为ip包定义单独的栏位,直接放入以太网包的data部分
head:长度为20到60字节
data:最长为65,515字节。
而以太网数据包的”数据”部分,最长只有1500字节。所以,若是IP数据包超过了1500字节,它就须要分割成几个以太网数据包,分开发送了。
传输层:遵循端口协议(tcp/udp协议)
传输层的由来:网络层的IP地址帮咱们区分子网,以太网的MAC帮咱们找到主机, 而后你们使用的都是应用程序,你的电脑上可能同时开启QQ,微信等多个应用程序那么咱们经过ip和Mac找到了目标计算机,如何标识这台主机上的应用程序,答案就是端口,端口即应用程序与网卡关联的编号
传输层功能:创建端口到端口的通讯
端口: 0~65535端口号.
1~1023系统占用的端口号.
1024~8000以内:通常都是有软件占用.
自定义端口: 8000 之后
tcp协议:
可靠传输,TCP数据包没有长度限制,理论上能够无限长,可是为了保证网络的效率,一般TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包没必要再分割。
以太网头|ip头|tcp头|数据
udp协议:
不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。
以太网头|ip头|udp头|数据
TCP的三次握手四次挥手
三次握手:
第一次: 客户端向服务器发送创建联系的syn请求和seq序号
第二次: 服务器向客户端回复ack确认号和创建联系的syn请求和seq序号
第三次: 客户端向服务器回复ack确认号
四次挥手:
第一次: 客户端向服务器发送断开联系的fin请求和seq序号
第二次: 服务器向客户端回复ack确认号
第三次: 服务器向客户端发送断开联系的fin请求和seq序号
第四次: 客户端向服务器回复ack确认号
udp与tcp的区别
一、TCP的优缺点 (1)TCP的优势: TCP的优势是:可靠、稳定。它体如今TCP在传递数据以前,会有三次握手来创建链接;在数据传递时,采用校验和、序列号、确认应答、超时重发、流量控制、拥塞控制,为了提升性能,还采用了滑动窗口、延迟应答和捎带应答等机制;在数据传完后,会断开链接以节约系统资源。 (2)TCP的缺点: TCP的缺点:运行速度慢,效率低,占用系统资源多,易被攻击。由于TCP在传递数据以前,要先创建链接,这会消耗时间;在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,并且要在每台设备上维护全部的传输链接,每一个链接都会占用系统的CPU、内存等资源;TCP有确认机制、三次握手机制,这致使TCP容易受到DOS、DDOS、CC等攻击。收到STN洪水攻击,是由于使用 TCP的时候服务器端须要listen,这时须要设置backlog。 二、UDP的优缺点 (1)UDP的优势:运行速度较快,比TCP安全。 1)运行速度快,由于 UDP链接没有TCP的三次握手、确认应答、超时重发、流量控制、拥塞控制等机制,并且UDP是一个无状态的传输协议,因此它在传递数据时很是快。 2)较安全,由于没有TCP的那些机制,UDP较TCP被攻击者利用的漏洞就会少一些。但UDP也是没法避免攻击的,好比:UDP Flood攻击等。 (2)UDP的缺点:不可靠,不稳定。 由于UDP没有TCP那些可靠的机制,在数据传递时,若是网络质量很差,就会很容易丢包。 三、TCP和UDP的特色 (1)TCP的特色 TCP协议是一种有链接、可靠的、面向字节流、相对比较慢、点对点的传输层协议。TCP协议适用于对可靠性要求比较高的场合。 (2)UDP的特色 UDP协议是一种无链接,不可靠、面向数据报、速度比较快、可实现一对一,多对一的传输层协议。UDP协议适用于对实时性有要求的场合。由于UDP不保证可靠性,因此UDP也没有重传机制,也没有拥塞机制,它只是尽最大努力交付数据。
使用TCP的应用:Web浏览器;文件传输程序。
使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP),微信qq。
应用层:遵循应用软件本身定义的协议
应用层由来: 用户使用的都是应用程序,均工做于应用层,互联网是开放的,你们均可以开发本身的应用程序,数据多种多样,必须规定好数据的组织形式
应用层功能:规定应用程序的数据格式。
socket套接字.
五层协议: 从传输层包括传输层如下,都是操做系统帮助咱们封装的各类head.你不用去关心.应用层与传输层之间存在一个socket套接字
# socket的套接字 ''' socket 套接字,它存在于传输层与应用层之间的抽象层, 1. 避免你学习各层的接口,以及协议的使用, socket已经封装好了全部的接口. 直接使用这些接口或者方法便可,使用起来方便,提高开发效率. 2. socket就是一个模块.经过使用学习模块提供的功能, 创建客户端与服务端的通讯,使用方便. '''
单个客户与服务端通讯.
服务端:
import socket # phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 1. 建立socket对象 phone = socket.socket() # 能够不写,默认TCP协议下的连接模式 # 2. 绑定ip地址和端口 phone.bind(('127.0.0.1', 8848)) # '127.0.0.1'本地回环地址 # 3. 监听 phone.listen(5) # 4. 接收链接 conn, addr = phone.accept() # 程序夯住,等待客户端的数据 from_client_data = conn.recv(1024) # 至多接收1024个字节 print(f'来自客户端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) conn.close() phone.close()
客户端:
import socket # 1. 建立socket对象 phone = socket.socket() # 能够默认不写 # 链接服务器ip地址与端口 phone.connect(('127.0.0.1', 8848)) # 发消息 to_server = input('>>>').strip() phone.send(to_server.encode('utf-8')) # 接收消息 from_server_data = phone.recv(1024) # 夯住,等待服务端的数据传过来 print(f'来自服务端消息:{from_server_data.decode("utf-8")}') # 关机 phone.close()
通讯循环.
服务端:
import socket phone = socket.socket() # 能够默认不写 phone.bind(('127.0.0.1', 8848)) # 本地回环地址 phone.listen(5) conn, addr = phone.accept() # 程序夯住 while 1: from_client_data = conn.recv(1024) # 至多接收1024个字节 print(f'来自客户端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) conn.close() phone.close() # 不管你的客户端是否正常关闭,服务端都应该正常关闭,而不是报错. # 改进版 import socket phone = socket.socket() # 能够默认不写 phone.bind(('127.0.0.1', 8888)) # 本地回环地址 phone.listen(5) conn, addr = phone.accept() # 程序夯住 while 1: try: from_client_data = conn.recv(1024) # 至多接收1024个字节 if from_client_data == b'q': # 接受到客户端发来的q 退出循环 break print(f'来自客户端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) except ConnectionResetError: break conn.close() phone.close()
客户端:
import socket phone = socket.socket() # 能够默认不写 phone.connect(('127.0.0.1', 8888)) while 1: to_server = input('>>>').strip() if to_server.upper() == 'Q': # 若是用户输入的是Q/q phone.send('q'.encode('utf-8')) # 向服务端发送 q break # 退出循环 phone.send(to_server.encode('utf-8')) from_server_data = phone.recv(1024) # 夯住,等待服务端的数据传过来 print(f'来自服务端消息:{from_server_data.decode("utf-8")}') phone.close()
通讯,链接循环.
服务端:
import socket phone = socket.socket() phone.bind(('127.0.0.1', 8888)) phone.listen(5) while 1: conn, addr = phone.accept() # 程序夯住 while 1: try: from_client_data = conn.recv(1024) # 至多接收1024个字节 if from_client_data == b'q': break print(f'来自客户端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) except ConnectionResetError: break conn.close() phone.close()
客户端:
import socket phone = socket.socket() # 能够默认不写 phone.connect(('127.0.0.1', 8888)) while 1: to_server = input('>>>').strip() if to_server.upper() == 'Q': phone.send('q'.encode('utf-8')) break phone.send(to_server.encode('utf-8')) from_server_data = phone.recv(1024) # 夯住,等待服务端的数据传过来 print(f'来自服务端消息:{from_server_data.decode("utf-8")}') phone.close()
利用socket完成获取远端命令的示例.
服务端
import socket import subprocess phone = socket.socket() phone.bind(('127.0.0.1', 8888)) phone.listen(5) conn, addr = phone.accept() while 1: try: cmd = conn.recv(1024) # dir obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,) result = obj.stdout.read() + obj.stderr.read() conn.send(result) except ConnectionResetError: break conn.close() phone.close()
客户端
import socket phone = socket.socket() phone.connect(('127.0.0.1', 8888)) while 1: cmd = input('>>>').strip() phone.send(cmd.encode('utf-8')) result = phone.recv(1024) # 夯住,等待服务端的数据传过来 print(result.decode('gbk')) phone.close()