【传输层协议TCP/UDP】
1 PORT协议(端口协议) 2 端口号用来(ip+port):标识一台计算机上面的某一个应用程序 3 端口号的范围:0-65535 4 这是因为传输层的协议:TCP、UDP等,它们的报头端口号长度是16bit所决定的!! 2的16次方 5 端口号特征:动态分配(类似于洗浴中心号码牌) 6 每一个应用程序都要有一个端口号!!! 7 8 ---------------------------------------------------------- 9 10 # 建议: 11 0-1024 系统默认需要使用的端口号,操作系统里面有一些固定的底层服务需要用的。别使用这些端口号!! 12 1024-8000 常见软件的端口号,可能已经被占掉了,也尽量别用! 13 8000之后的 以后写项目推荐使用!!! 14 15 软件在启动的时候是可以指定端口号的,就是说自己可以去指定用哪个端口号的,常用的已经被指定完了, 16 不指定一个端口号,就会被计算机动态的分配一个端口号!!! 17 18 注意,端口号是不固定的,即可以由用户手工可以分配(当然,一般在软件编写时就已经定义)。 19 当然,有很多应用软件有公认的默认的端口,比如FTP:20和21,HTTP:80,TELNET:23等等 20 一个软件可以拥有多个端口号,这证明这个软件拥有不止一个网络功能。 21 22 ------------------------------------------------ 23 URL:统一资源定位符(网址) 24 网址本质是有IP和PORT组成的!!!! 25 26 ------ 27 28 IP:PORT:能够定位全世界独一无二的一台计算机上面的某一个应用程序 29 114.55.205.139:80 30 ------ 31 32 我们之所以不直接使用IP+PORT的原因是太难记 所以发明了域名(网址) 33 域名解析:将网址解析成IP+PORT
---------------------------------------------
重点!!!!!!
1 # TCP与UDP都是用来规定通信方式的 2 3 TCP协议(传输控制协议) 4 当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。 5 这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立 6 一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路, 7 直到它被一方或双方关闭为止。 8 tcp协议就是控制数据数据包在传输过程中的规范格式 9 是一种面向连接的,可靠的,基于字节流的传输层协议。 10 11 12 (Transmission Control Protocol)传输控制协议 13 通俗地说TCP就是对于传输、发送、通信进行控制的协议。 14 15 16 1.TCP协议(重要) 17 TCP协议的特点是:面向连接、字节流、可靠传输 18 TCP的机制具有:校验机制、可靠、数据传输稳定 19 20 --------------------------------------------- 21 # 三次握手:建链接 22 1.TCP协议也称为可靠协议(数据不容易丢失) 23 造成数据不容易丢失的原因不是因为有双向通道,而是因为有反馈机制!!!!! 24 给对方发消息之后会保留一个副本 直到对方回应消息收到了才会删除 25 否则会在一定的时间内反复发送 26 27 28 2.洪水攻击 29 同一时间有大量的客户端请求建立链接,会导致服务端一直处于SYN_RCVD状态!!!! 30 3.服务端如何区分客户端建立链接的请求 31 可以对请求做唯一标识 32 --------------------------------------------- 33 34 # 四次挥手:断链接 35 1.四次不能合并为三次 36 因为中间需要确认消息是否发完(TIME_WAIT) 37 38 --------------------------------------------- 39 ps:课下可以深入研究一下TCP图片上每个状态的具体情况 40 41 需要注意: 42 TCP协议用于1对1,即不能用于基于广播和多播的应用程序 43 TCP连接双方的收发数据次数不一定相同,即发送多次的数据包,可能会被对方1次全部接收 44 TCP在发送数据报后,必须得到接收方的应答,才认为传输成功,所以是可靠的 45 TCP采用超时重传机制,超过时间没收到应答,就会重新发送。
(三次握手)
三次握手建立通道:建立链接是为了传数据做准备的,三次握手即可 1.客户端发送syn包---->服务器 2.服务器收到syn包,发送ack确认包---->客户端 3.客户端收到ack确认包,发送ack确认包---->服务器 三次握手完毕,建立双向通道
(四次挥手)
四次挥手断开通道:断开链接是为了节省资源做准备的,四次挥手即可 1.客户端发送fin包---->服务器 2.服务器收到fin包,发送ack确认包---->客户端 3.服务器发送fin包---->客户端 4.客户端收到fin包,发送ack确认包---->服务器 四次挥手完毕,断开双向通道
PS补充:
1 PS:当服务端大量处于TIME_WAIT状态时,会导致端口资源耗尽,无法建立新的链接 2 基于udp协议通信:不需要建立双向通信的通道 3 C<--------------------S 4 S<--------------------C 5 udp协议:不可靠传输,速度快,但是容易丢包
tcp半链接池:(相当于一个等待服务窗口:如网上客服咨询等待)backlog
【链接请求1,链接请求2,链接请求3.。。】
。
。
。
【应用层】
应用层相当于是程序员自己写的应用程序,里面的协议非常的多
常见的有:HTTP、HTTPS、FTP
ps:后续框架部分再做介绍
【socket套接字】
socket是网络通信中的一个抽象概念,它是一个通信链的句柄,可以用来实现不同主机之间的进程通信
import socket
1 如果我们需要编写基于网络进行数据交互的程序 2 意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统) 3 4 socket类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口 5 ----------------------------------------- 6 7 理解socket 8 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中, 9 Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说, 10 一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。 11 12 ----------------------------------------- 13 14 Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说, 15 一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。 16 17 ----------------------------------------- 18 19 socket也叫套接字 20 基于文件类型的套接字家族(单机) 21 AF_UNIX 22 ------------- 23 基于网络类型的套接字家族(联网) 24 AF_INET 25 26 ----------------------------------------- 27 28 在这里主要学习利用socket完成TCP/IP通讯,首先需要生成两个对象, 29 一个是客户端(client),一个是服务端(sever)。
(工作流程)
(基于tcp协议的简单套接字)
PS:为什么要先运行服务端,再运行客户端?
因为客户端需要连接服务端,所以服务端必须先运行起来,等待客户端的连接。
而客户端是主动连接服务端的,所以客户端可以先运行起来。
1 服务端 2 3 import socket 4 5 # 1.买手机 6 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET:表示ipv4,SOCK_STREAM:表示使用tcp协议 7 8 # 2.绑定手机卡 ip+端口,如果ip是:0.0.0.0,表示本机的所有ip都可以使用 9 phone.bind(("127.0.0.1", 8082)) # (绑定的是服务端的id)0-65535,1024以前的被系统保留使用 10 11 # 3.开机,监听状态 12 phone.listen(5) # 5表示半链接池的大小(backlog=5) 13 print('服务端启动完成,监听地址为:%s:%s' % (socket.gethostname(), 8082)) 14 15 # 4.等待电话链接请求 16 # conn:表示与客户端进行通信的socket,client_addr:表示客户端的ip和端口 17 conn, client_addr = phone.accept() 18 print(conn) 19 print('客户端的ip和端口:', client_addr) 20 21 # 5.接收消息\发送消息 22 data = conn.recv(1024) # 1024表示一次接收1024个字节 23 print('客户端发送的数据:', data.decode('utf-8')) 24 conn.send(data.upper()) # 将接收到的数据转换为大写,并发送给客户端 25 26 # 6.关闭连接 27 conn.close() 28 29 # 7.关闭手机(可选操作,可有可无) 30 phone.close() 31 32 33 ------------------------------------------------------------------------------------- 34 客户端 35 36 37 import socket 38 39 40 # 1.买手机:AF_INET--地址家族,实现网络通信 SOCK_STREAM---基于什么协议:流式协议(tcp) 41 # SOCK_DGRAM---数据报协议(udp) 42 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 43 44 # 2.拨通服务端电话,发送连接请求 45 phone.connect(('127.0.0.1', 8082)) # connect()括号里是服务端ip和端口号=client_addr 46 47 # 3.通信 48 phone.send('hello tank 早上好'.encode('utf-8')) 49 50 # 4.关闭连接,对应的是服务端的conn 51 phone.close()
(通信循环--解决Bug)
1 # 5.接收消息\发送消息 2 while True: 3 try: 4 data = conn.recv(1024) # 1024表示本次接收的最大字节数,收到的是bytes类型 5 if len(data) == 0: 6 # 在unix/linux下,一旦data收到的是空,就意味着是一种异常的行为:客户端非法断开了链接 7 break 8 print('客户端发来的消息:', data.decode('utf-8')) 9 conn.send(data.upper()) 10 except Exception: 11 # 针对windows系统客户端非法断开解决办法 12 break 13 14 -------------------------------------------------- 15 客户端 16 17 # 3.通信 18 # 客户端如果强行断开连接,会造成服务端死循环 19 while True: 20 msg = input('输入要发送的消息>>:').strip() 21 # 输入空格,不发送,如果输入空,客户端会阻塞 22 if len(msg) == 0: continue 23 # 退出循环 24 # if msg == 'quit': break 25 # time.sleep(2) 26 # phone.send(b.ini'hello') # phone.send('hello'.encode('utf-8')),必须是bytes类型 27 phone.send(msg.encode('utf-8')) 28 print('=====?') # 验证什么造成了阻塞,阻塞在哪里 29 data = phone.recv(1024) # 上面一行代码运行,说明收阻塞了 30 print(data.decode('utf-8'))
。
。
(链接循环案例)
服务端应该满足的特点:
1.一直提供服务
2.并发的提供服务
1 服务端 2 3 import socket 4 5 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 6 7 # 2.绑定手机卡 8 phone.bind(("127.0.0.1", 8083)) 9 10 # 3.开机 11 phone.listen(5) 12 print('服务端启动完成,监听地址为:%s:%s' % (socket.gethostname(), 8083)) 13 14 # 4.等待电话链接请求,拿到电话连接conn 15 # 当上一客户服务完成,接待下一个客户的做法: 16 # 链接循环 17 while True: 18 conn, client_addr = phone.accept() 19 print('客户端的ip和端口:', client_addr) 20 21 # 5.接收消息\发送消息 22 while True: 23 try: 24 data = conn.recv(1024) 25 if len(data) == 0: 26 break 27 print('客户端发来的消息:', data.decode('utf-8')) 28 conn.send(data.upper()) 29 except Exception: 30 # 针对windows系统客户端非法断开解决办法 31 break 32 33 # 6.关闭连接 34 conn.close() 35 36 # 7.关闭手机 37 phone.close() 38 39 40 ------------------------------------------------------------------------------------ 41 客户端1: 42 43 import socket 44 import time 45 46 47 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48 49 # 2.拨通服务端电话 50 phone.connect(('127.0.0.1', 8083)) 51 52 # 3.通信循环 53 while True: 54 msg = input('输入要发送的消息>>:').strip() 55 if len(msg) == 0: continue 56 # 退出循环 57 # if msg == 'quit': break 58 # time.sleep(2) 59 # phone.send(b.ini'hello') # phone.send('hello'.encode('utf-8')),必须是bytes类型 60 phone.send(msg.encode('utf-8')) 61 print('=====?') 62 data = phone.recv(1024) 63 print(data.decode('utf-8')) 64 65 # 4.关闭连接 66 phone.close() 67 68 69 70 =========================================== 71 当其中一个客户端断开连接,第二个客户端发送建立连接请求,服务端能继续服务
【半链接池】
1 定义: 2 半连接池是一个容器或机制,用于存储和管理在网络通信中形成的半连接状态。 3 4 背景: 5 在TCP协议中,建立连接的过程包括三次握手。当客户端发送SYN包到服务器,服务器响应ACK包并等待客户端的确认时,这种状态被称为半连接状态。 6 在高并发的网络环境中,如果短时间内有大量客户端发起连接请求,服务器可能会因为处理不过来这些半连接状态而导致资源耗尽,进而影响服务性能。 7 8 工作原理: 9 当客户端请求成功被服务端接收后,服务端不会立即对该请求发出响应,而是将这些请求存储在半连接池中。 10 只要半连接池没有满,客户端的请求都会进入服务端。如果半连接池已满,新的请求将被阻拦并显示等待。 11 半连接池通过服务端响应最早进入的客户端请求,达到管理半连接状态、防止资源耗尽的目的。 12 13 作用: 14 限制同一时间内的客户端请求数,避免服务器因处理过多半连接状态而资源耗尽。 15 提高服务器在高并发环境下的稳定性和性能。 16 17 相关概念: 18 SYN洪水攻击:一种网络攻击方式,通过不断产生半连接状态,让服务器无法处理正常请求。 19 连接池:一种通用的技术,用于提高资源的利用率和系统的性能。除了半连接池外,还有数据库连接池、线程池等。 20 注意: 21 半连接池限制的是同一时间的客户端请求数,而非连接数。 22 合理地配置半连接池的大小对于服务器的性能和稳定性至关重要。
。
。
。
(udp协议套接字)
1 服务端 2 3 import socket 4 5 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 数据报协议==》udp协议 6 7 server.bind(('127.0.0.1', 8083)) 8 9 while True: 10 data, client_addr = server.recvfrom(1024) 11 server.sendto(data.upper(), client_addr) 12 13 server.close() 14 15 16 ----------------------------------------------------------------------------------- 17 客户端 18 19 import socket 20 21 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 22 while True: 23 msg = input('>>:').strip() 24 client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8083)) 25 res = client.recvfrom(1024) 26 print(res) 27 28 client.close()
(UDP和TCP的区别)
1 TCP与UDP都是用来规定通信方式的 2 区别: 3 TCP协议称之为流式协议、可靠协议(数据不容易丢失) 4 面向连接 5 UDP协议称之为数据报协议、不可靠协议 6 面向无连接 7 8 # UDP用在哪里? 9 早期的QQ使用的就是纯生的UDP协议 10 现在QQ自己添加了很多技术和功能 11 使用UDP的原因就是因为很简单 快捷 粗暴 只要指定对方的地址就可以发消息了 而TCP还要建立三握四挥 12 13 TCP我们可以打比方为打电话 你一句我一句 14 UDP我们可以看成是发短信 只要发了就行 不管对方看不看
。
。
。
【粘包问题,UDP协议没有粘包问题】
(1)什么是粘包问题