客户端与服务器端架构,这种架构也是从用户层面(也能够是物理层面)来划分的。python
这里的客户端通常泛指客户端应用程序EXE,程序须要先安装后,才能运行在用户的电脑上,对用户的电脑操做系统环境依赖较大。编程
C: Client (客户端)设计模式
S: Server (服务端)浏览器
优势:缓存
缺点:安全
浏览器端与服务器端架构,这种架构是从用户层面来划分的。服务器
Browser浏览器,其实也是一种Client客户端,只是这个客户端不须要你们去安装什么应用程序,只需在浏览器上经过HTTP请求服务器端相关的资源(网页资源),客户端Browser浏览器就能进行增删改查。网络
B: Browser ( 浏览器端 )架构
S: Server (服务端)并发
优势:
缺点:
总结:
CS架构响应速度快,安全性强,通常应用于局域网中,可是开发维护成本高;BS能够实现跨平台,客户端零维护,可是个性化能力低,响应速度较慢。
问题:数据放在服务端和客户端的利与弊?
对电信号来作分组。之前每一个公司都有本身的分组方式,后来造成了统一的标准,即以太网协议ethernet。
ethernet规定:一组电信号构成一个数据报,叫作'帧',每一数据帧分红:报头head和数据data两部分
- | - |
---|---|
head | data |
head中包含的源和目标地址由来:ethernet规定接入internet的设备都必须具有网卡,发送端和接收端的地址即是指网卡的地址,即mac地址。
mac地址:每块网卡出厂时都被烧制上一个世界惟一的mac地址,长度为48位2进制,一般由12位16进制数表示(前六位是厂商编号,后六位是流水线号)
主机之间“一对全部”的通信模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,全部主机均可以接收到全部信息(无论你是否须要),因为其不用路径选择,因此其网络成本能够很低廉。有线电视网就是典型的广播型网络,咱们的电视机其实是接受到全部频道的信号,但只将一个频道的信号还原成画面。在数据网络中也容许广播的存在,但其被限制在二层交换机的局域网范围内,禁止广播数据穿过路由器,防止广播数据影响大面积的主机。
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。
主机发送信息时将包含目标IP地址的ARP请求广播到网络上的全部主机,并接收返回消息,以此肯定目标的物理地址。
路由器(Router),是链接因特网中各局域网、广域网的设备,它会根据信道的状况自动选择和设定路由,以最佳路径,按先后顺序发送信号。 路由器是互联网络的枢纽,"交通警察"。目前路由器已经普遍应用于各行各业,各类不一样档次的产品已成为实现各类骨干网内部链接、骨干网间互联和骨干网与互联网互联互通业务的主力军。路由和交换机之间的主要区别就是交换机发生在OSI参考模型第二层(数据链路层),而路由发生在第三层,即网络层。这一区别决定了路由和交换机在移动信息的过程当中需使用不一样的控制信息,因此说二者实现各自功能的方式是不一样的。
路由器(Router)又称网关设备(Gateway)是用于链接多个逻辑上分开的网络,所谓逻辑网络是表明一个单独的网络或者一个子网。当数据从一个子网传输到另外一个子网时,可经过路由器的路由功能来完成。所以,路由器具备判断网络地址和选择IP路径的功能,它能在多网络互联环境中,创建灵活的链接,可用彻底不一样的数据分组和介质访问方法链接各类子网,路由器只接受源站或其余路由器的信息,属网络层的一种互联设备。
局域网(Local Area Network,LAN)是指在某一区域内由多台计算机互联成的计算机组。通常是方圆几公里之内。局域网能够实现文件管理、应用软件共享、打印机共享、工做组内的日程安排、电子邮件和传真通讯服务等功能。局域网是封闭型的,能够由办公室内的两台计算机组成,也能够由一个公司内的上千台计算机组成。
所谓”子网掩码”,就是表示子网络特征的一个参数。它在形式上等同于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地址的主机能够提供许多服务,好比Web服务、FTP服务、SMTP服务等,这些服务彻底能够经过1个IP地址来实现。那么,主机是怎样区分不一样的网络服务呢?显然不能只靠IP地址,由于IP地址与网络服务的关系是一对多的关系。其实是经过“IP地址+端口号”来区分不一样的服务的。
人们按照分工不一样把互联网协议从逻辑上划分了层级:(通常做为开发人员,掌握应传网数物 五层便可):
每层运行常见物理设备:
每层运行常见的协议:
构成
网络通讯的数据传输介质,由链接不一样结点的电缆与设备共同构成。
功能:
基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0。
由来
单纯的电信号0和1没有任何意义,必须规定电信号多少位一组,每组什么意思。
功能
基于以太网协议,定义了电信号的分组方式。
功能
引入一套新的地址用来区分不一样的广播域/子网,这套地址即网络地址
由来
有了ethernet、Mac地址、广播的发送方式,世界上的计算机就能够彼此通讯了,问题是世界范围的互联网是由 一个个彼此隔离的小的局域网组成的,那么若是全部的通讯都采用以太网的广播方式,那么一台机器发送的包全世界都会收到。
用于标识惟一的一台计算机(局域网)的地址。
3.3.2 arp协议
由来
通讯是基于Mac的广播方式实现,计算机在发包时,获取自身的Mac是容易的,如何获取目标主机的Mac,就须要经过arp协议
功能
广播的方式发送数据包, 全部主机接收后拆开包,发现目标IP为本身的,就响应,返回本身的Mac。
功能
创建端口到端口的通讯
由来
网络层的IP帮咱们区分子网,以太网层的Mac帮咱们找到主机,而后你们使用的都是应用程序,你的电脑上可能同时开启qq,暴风影音,等多个应用程序。
那么咱们经过IP和Mac找到了一台特定的主机,如何标识这台主机上的应用程序,答案就是端口,端口即应用程序与网卡关联的编号。
有了Mac地址+IP地址+端口,咱们就能肯定世界上独一无二的一台计算机上的应用程序。
可靠传输,TCP数据包没有长度限制,理论上能够无限长,可是为了保证网络的效率,一般TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包没必要再分割。
- | - | - | - |
---|---|---|---|
以太网头 | IP头 | TCP头 | 数据 |
不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。
- | - | - | - |
---|---|---|---|
以太网头 | IP头 | UDP头 | 数据 |
功能
规定应用程序的数据格式。
由来
用户使用的都是应用程序,均工做于应用层,互联网是开发的,你们均可以开发本身的应用程序,数据多种多样,必须规定好数据的组织形式 。
TCP协议:
提供面向链接的服务,在传送数据以前必须先创建链接,数据传送完成后要释放链接。所以TCP是一种可靠的的运输服务,可是正由于这样,不可避免的增长了许多的开销,好比确认,流量控制等。对应的应用层的协议主要有 SMTP,TELNET,HTTP,FTP 等。
UDP协议:
在传送数据前不须要先创建链接,远地的主机在收到UDP报文后也不须要给出任何确认。虽然UDP不提供可靠交付,可是正是由于这样,省去和不少的开销,使得它的速度比较快,好比一些对实时性要求较高的服务,就经常使用的是UDP。对应的应用层的协议主要有 DNS,TFTP,DHCP,SNMP,NFS 等。
经常使用的端口号
操做系统中,通常0-1024的端口都被默认使用了(0-1024不要动),尽可能使用8000以后的端口号。
应用程序 | FTP | TFTP | TELNET | SMTP | DNS | HTTP | SSH | MYSQL |
---|---|---|---|---|---|---|---|---|
熟知端口 | 21,20 | 69 | 23 | 25 | 53 | 80 | 22 | 3306 |
传输层协议 | TCP | UDP | TCP | TCP | UDP | TCP | TCP | TCP |
【问题1】为何链接的时候是三次握手,关闭的时候倒是四次握手?
答:由于当Server端收到Client端的SYN链接请求报文后,能够直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。可是关闭链接时,当Server端收到FIN报文时,极可能并不会当即关闭SOCKET,因此只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端全部的报文都发送完了,我才能发送FIN报文,所以不能一块儿发送。故须要四步握手。
【问题2】为何TIME_WAIT状态须要通过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,咱们能够直接进入CLOSE状态了,可是咱们必须假象网络是不可靠的,有能够最后一个ACK丢失。因此TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server若是没有收到ACK,将不断重复发送FIN片断。因此Client不能当即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK以后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。若是在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片断在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。若是直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP链接。
【问题3】为何不能用两次握手进行链接?
答:3次握手完成两个重要的功能,既要双方作好发送数据的准备工做(双方都知道彼此已准备好),也要容许双方就初始序列号进行协商,这个序列号在握手过程当中被发送和确认。如今把三次握手改为仅须要两次握手,死锁是可能发生的。做为例子,考虑计算机S和C之间的通讯,假定C给S发送一个链接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为链接已经成功地创建了,能够开始发送数据分组。但是,C在S的应答分组在传输中被丢失的状况下,将不知道S 是否已准备好,不知道S创建什么样的序列号,C甚至怀疑S是否收到本身的链接请求分组。在这种状况下,C认为链接还未创建成功,将忽略S发来的任何数据分 组,只等待链接确认应答分组。而S在发出的分组超时后,重复发送一样的分组。这样就造成了死锁。
【问题4】若是已经创建了链接,可是客户端忽然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端若是出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会从新复位这个计时器,时间一般是设置为2小时,若两小时尚未收到客户端的任何数据,服务器就会发送一个探测报文段,之后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭链接。
Socket是应用层与TCP/IP协议族通讯的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来讲,一组简单的接口就是所有,让Socket去组织数据,以符合指定的协议。
因此,咱们无需深刻理解tcp/udp协议,socket已经为咱们封装好了,咱们只须要遵循socket的规定去编程,写出的程序天然就是遵循tcp/udp标准的。
服务器端先初始化Socket,而后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端链接。在这时若是有个客户端初始化一个Socket,而后链接服务器(connect),若是链接成功,这时客户端与服务器端的链接就创建了。客户端发送数据请求,服务器端接收请求并处理请求,而后把回应数据发送给客户端,客户端读取数据,最后关闭链接,一次交互结束。
# File-服务端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp称为流式协议,udp称为数据报协议SOCK_DGRAM # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1', 8081)) phone.listen(5) # 半链接池,限制的是请求数 print('start....') conn, client_addr = phone.accept() #(三次握手创建的双向链接,(客户端的ip,端口)) print(conn) print(client_addr) #五、通讯:收\发消息 data = conn.recv(1024) #最大接收的字节数 print('来自客户端的数据', data) conn.send(data.upper()) #六、断开链接 conn.close() #七、结束服务 phone.close()
# File-客户端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(phone) phone.connect(('127.0.0.1', 8081)) # 指定链接服务端ip和端口 #三、通讯:发\收消息 phone.send('hello'.encode('utf-8')) # phone.send(bytes('hello',encoding='utf-8')) data = phone.recv(1024) print(data) #四、关闭 phone.close()
# File-服务端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp称为流式协议,udp称为数据报协议SOCK_DGRAM # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1', 8080)) phone.listen(5) # 半链接池,限制的是请求数 print('start....') while True: # 链接循环 conn, client_addr = phone.accept() #(三次握手创建的双向链接,(客户端的ip,端口)) # print(conn) print('已经有一个链接创建成功', client_addr) #五、通讯:收\发消息 while True: # 通讯循环 try: print('服务端正在收数据...') data = conn.recv(1024) #最大接收的字节数,没有数据会在原地一直等待收,即发送者发送的数据量必须>0bytes # print('===>') if len(data) == 0: break #在客户端单方面断开链接,服务端才会出现收空数据的状况 print('来自客户端的数据', data) conn.send(data.upper()) except ConnectionResetError: break #六、断开链接 conn.close() #七、中止服务 phone.close()
# File-客户端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.connect(('127.0.0.1', 8080)) # 指定链接服务端ip和端口 #三、通讯:发\收消息 while True: # 通讯循环 msg = input('>>: ').strip() #msg='' if len(msg) == 0: continue phone.send(msg.encode('utf-8')) # print('has send----->') data = phone.recv(1024) # print('has recv----->') print(data) #四、断开链接 phone.close()