11月16日内容总结——OSI传输层之TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
一、传输层之TCP与UDP协议
TCP与UDP协议都是用来规定通信方式的。比如我们在聊天的时候可以随心所欲的聊,有些时候又需要遵循一些规律进行聊天。
当我们跟关系很好的朋友聊天的时候,百无禁忌,上到国家,下到生活中的琐事都可以聊。这就相当于没有设立规定时的通信。
当我们在上课的时候,只能跟老师和同学沟通学习相关的问题。在写作文的时候需要开头空两格,需要分段。写信时需要用上书信格式。这些都相当于设立了规定后的通信。
ps:不遵循上述协议也可以通信 只不过遵循了更合规合法合理!!!
1.TCP协议(重要)
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。
当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。
这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。
三次握手建链接(白话版)
1.三次握手建立连接的过程(白话版)
第一次握手:客户端这边向服务端发送建立连接的请求(SYN seq = x)
第二次握手:服务端接收请求并回应,回应的同时向客户端发送建立连接的请求(这里可以看成同时进行了两步,如果服务端同意建立连接,这时候就会建立起客户端发送数据到服务端的数据传输通道,之后的服务端向客户端发送建立连接的请求是为了建立服务端返回数据到客户端的数据传输通道。SYN seq = y,ACK = x + 1)
第三次握手:客户端向服务端进行回应(ACK = y + 1)这时就建立起了两者的双向数据传输通道
2.TCP协议也称为可靠协议(数据不容易丢失)
造成数据不容易丢失的原因不是因为有双向通道 而是因为有反馈机制
给对方发消息之后会保留一个副本 直到对方回应消息收到了才会删除
否则会在一定的时间内反复发送。
3.洪水攻击
同一时间有大量的客户端请求建立链接就会导致服务端一直处于SYN_RCVD状态
4.服务端如何区分客户端建立链接的请求
当我们在建立连接的时候,客户端会发送上图中的请求seq,这个seq带有一串数字,类似识别号码,服务端端受到请求进行反馈的时候返回的信息就是上图中的ACK,ACK会把seq中的识别号码+1然后返回回来,因为不同的客户端发送seq的时候有不同的识别号码,服务端靠这种方式来区分请求(对请求做唯一标识)。
三次握手专业版
刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。
进行三次握手:
第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN。此时客户端处于
SYN_SENT
状态。首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于
SYN_RCVD
的状态。在确认报文段中SYN=1,ACK=1(确认值(Acknowledgement),为1便是确认连接,为0就是不在连接状态),确认号ack=x+1(确认编号(Acknowledgement Number),即接收到的上一次远端主机传来的seq然后+1,再发送给远端主机),初始序号seq=y。
第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于
ESTABLISHED
状态。服务器收到 ACK 报文之后,也处于ESTABLISHED
状态,此时,双方已建立起了连接。确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。
发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)。
在socket编程中,客户端执行connect()时,将触发三次握手。
四次挥手断连接(白话版)
1.四次挥手断开连接的过程(白话版)
第一次挥手:当客户端没有信息需要发送给服务端的时候,客户端会发送断开连接的请求(SYN seq = x+2)
第二次挥手:这时服务端会回应客户端,确认断开客户端传输信息给服务端的数据传输通道(ACK=x+3)
TIME_WAIT状态:当断开客户端传输数据到服务端的数据传输通道后,服务端需要先确认是否还有消息需要发送给客户端,发送完毕、确认无误后才会继续后续操作断开连接
第三次挥手:服务端向客户端发送断开通道连接的请求(seq = y + 1)
第四次挥手:客户端向服务端发送回应然后断开服务端跟客户端进行数据传输的通道(ACK = y + 2)
2.四次不能合并为三次
因为中间需要确认消息是否发完(TIME_WAIT)
三次握手和四次挥手也可以看成是小情侣谈恋爱的过程:
三次握手:表白在一起
四次挥手:决裂要分手
四次挥手专业版
建立一个连接需要三次握手,而终止一个连接要经过四次挥手(也有将四次挥手叫做四次握手的)。这由TCP的半关闭(half-close)造成的。所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送端还能接收来自另一端数据的能力。
TCP 连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务端均可主动发起挥手动作。
刚开始双方都处于ESTABLISHED
状态,假如是客户端先发起关闭请求。四次挥手的过程如下:
- 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于
FIN_WAIT1
状态。
即发出连接释放报文段(FIN=1,序列号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。 - 第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于
CLOSE_WAIT
状态。
即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。 - 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于
LAST_ACK
的状态。
即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。 - 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于
TIME_WAIT
状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就关闭连接了,处于CLOSED
状态。
即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
收到一个FIN只意味着在这一方向上没有数据流动。客户端执行主动关闭并进入TIME_WAIT是正常的,服务端通常执行被动关闭,不会进入TIME_WAIT状态。
在socket编程中,任何一方执行close()操作即可产生挥手操作。
2.UDP协议
UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
早期的QQ使用的是纯生的(没有加任何额外功能)UDP协议,导致很容易出现数据丢失,接收不到。现在的QQ自己添加了很多技术和功能。
使用UDP的原因就是因为很简单:快捷、粗暴,只要指定对方的地址就可以发消息了
3.tcp和udp的对比
上面的TCP协议相当于打电话一样,双方有来有回
UDP协议就相当于发短信,信息发出去了,但是不一定有回应,因此也称之为数据报协议、不可靠协议
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快
二、应用层简介
应用层相当于是程序员自己写的应用程序 里面的协议非常的多
常见的有:HTTP、HTTPS、FTP
ps:后续框架部分再做介绍
三、socket模块
1、简介
如果我们需要编写基于网络进行数据交互的程序 意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
socket模块类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口
ps:socket也叫套接字
2、基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
3、基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)
四、socket代码简介
服务端代码
import socket
# 1.产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket() # 括号内不写参数 默认就是TCP协议 family=AF_INET基于网络的套接字 type=SOCK_STREAM流式协议即TCP
# 2.绑定一个固定的地址(服务端必备的条件)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1为本地回环地址 只有自己的电脑可以访问,8080为端口号
# 3.设立半连接池(后面会讲)
server.listen(5)
# 4.等待接客
sock, addr = server.accept() # return sock, addr 三次握手
print(sock, addr) # sock就是双向通道 addr就是客户端地址
# 5.服务客人
data = sock.recv(1024) # 接收客户端发送过来的消息 1024字节(基于网络传输数据得是二进制)
print(data.decode('utf8')) # 因为二进制我们看不懂,所以要解码
sock.send('尊敬的客人 您说什么就是什么 一切按照您的要求来'.encode('utf8')) # 给客户端发送消息 注意消息必须是bytes类型
# 6.关闭双向通道
sock.close() # 四次挥手
# 7.关闭服务端
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()
五、socket代码优化
1.聊天内容自定义
针对消息采用input获取
2.让聊天循环起来
将聊天的部分用循环包起来(三次握手的代码开始包起来)
3.用户输入的消息不能为空
本质其实是两边不能都是recv或者send 一定是一方收一方发
4.服务端多次重启可能会报错
Address already in use
主要是mac电脑会报
方式1:改端口号
方式2:
#加入一条socket配置,重用ip和端口
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字
sk.listen() #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024) #接收客户端信息
print(ret) #打印客户端信息
conn.send(b'hi') #向客户端发送信息
conn.close() #关闭客户端套接字
sk.close() #关闭服务器套接字(可选)
5.当客户端异常断开的情况下 如何让服务端继续服务其他客人?
windows服务端会直接报错
mac服务端会有一段时间反复接收空消息延迟报错
处理方式:使用异常处理、空消息判断,对上面的情况进行判断并给出解决方案
服务端代码:
import socket
from socket import SOL_SOCKET, SO_REUSEADDR
server = socket.socket()
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8081))
server.listen(5)
while True: # 链接循环
sock, addr = server.accept()
while True: # 通信循环
try:
# 当客户端输入为空的时候通过循环跳过后续代码,防止程序报错
data = sock.recv(1024)
if len(data) == 0:
break
print(f'来自于客户端{addr}的消息>>>:', data.decode('utf8'))
msg = input('请输入发送给客户端的消息(不能发空消息)>>>:').strip()
# 返回的信息设置成自定义
sock.send(msg.encode('utf8'))
except BaseException:
# 当客户端直接退出的时候服务端这边会报错,我们用异常处理让程序跳过这些会报错的代码,继续运行
break
客户端代码:
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8081))
while True:
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
# 把发送的信息设置成自定义
if len(msg) == 0:
print('不能发送空消息')
continue
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))
六、半连接池的概念
server.listen(5) # 半连接池
当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题)
假设服务端只有一个人的情况下
比如上面我们半连接池设置成五个,在优化后的代码中,由于用while循环包裹了代码,当我们在运行代码的时候可以这样理解,第一个客户端就会直接跟服务端进行交互,除此之外还有五个客户端可以排队,但是发出去的信息服务端那边暂时不会处理,要等到第一个客户端处理结束断开连接才会根据先后顺序依次往后处理
在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可
11月16日内容总结——OSI传输层之TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念的更多相关文章
- 传输层的TCP和UDP协议
作者:HerryLo 原文永久链接: https://github.com/AttemptWeb... TCP/IP协议, 你一定常常听到,其中TCP(Transmission Control Pro ...
- 11月16日《奥威Power-BI基于SQL的存储过程及自定义SQL脚本制作报表》腾讯课堂开课啦
上周的课程<奥威Power-BI vs微软Power BI>带同学们全面认识了两个Power-BI的使用情况,同学们已经迫不及待想知道这周的学习内容了吧!这周的课程关键词—— ...
- 2016年11月16日 星期三 --出埃及记 Exodus 20:7
2016年11月16日 星期三 --出埃及记 Exodus 20:7 "You shall not misuse the name of the LORD your God, for the ...
- 北京Uber优步司机奖励政策(11月16日~11月22日)
用户组:人民优步“关羽组”(适用于11月16日-11月22日)奖励政策: 滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/ ...
- UNIX网络编程---传输层:TCP、UDP、SCTP(二)
UNIX网络编程----传输层:TCP.UDP.SCTP 一.概述 本章的焦点是传输层:包括TCP.UDP.和SCTP(流控制传输协议).SCTP是一个较新的协议,最初设计用于跨因特网传输电话信令. ...
- 计算机网络-传输层(1)UDP协议
UDP协议基于Internet IP协议,只提供两个基础功能: 分用/复用 分用:主机接收到IP数据报(datagram),每个数据报携带源IP地址.目的IP地址且携带一个传输层的段(Segment) ...
- 2018年11月16日SQL Server实验内容(触发器实验)
--注意:先把studentmanager数据库中的所有表用select into命令复制一份, --然后用复制后新表完成下面的实验,同时,对每个触发器都要进行验证. select *into dep ...
- 2018年11月16日 我和SB交流有代沟-继续字符串4
test="abcdeffedcba" v=test.lstrip("bcabc")#寻找的是最多匹配然后移除指定字符串 print("1.lstri ...
- linux学习第四天 (Linux就该这么学)2018年11月16日
今天主要讲了 管道符,重写向与环境变量 输入输出重写向 标准输出重写向 (标准,覆盖,错误) > 将标准输出重写向到一个文件中 >> 追加到文件 2>错误输出重定向 2> ...
- 11月16日NGK公链第13期官方快讯!
随机推荐
- 「浙江理工大学ACM入队200题系列」问题 K: 零基础学C/C++84——奇偶ASCII值判断
本题是浙江理工大学ACM入队200题第八套中的K题 我们先来看一下这题的题面. 题面 题目描述 任意输入一个字符,判断其ASCII是否是奇数,若是,输出YES,否则,输出NO; 例如,字符A的ASCI ...
- SSH(五)spring整合hibernate
一.创建hibernate实体映射文件. 在实体所在包创建映射文件product.hbm.xml,引入hibernate的映射约束.(该约束位于hibernate3.jar里面hibernate-ma ...
- 在 win11 下搭建并使用 ubuntu 子系统(同时测试 win10)——(附带深度学习环境搭建)
对于一个深度学习从事者来说,Windows训练模型有着诸多不便,还好现在Windows的Ubuntu子系统逐渐完善,近期由于工作需求,配置了Windows的工作站,为了方便起见,搭建了Ubuntu子系 ...
- Zabbix技术分享——使用Zabbix6.0监控业务日志
企业日常IT运维过程中,常会碰到需要监控业务日志的情况,以下将介绍如何使用Zabbix6.0监控业务日志. 应用场景描述: 企业IT运维部门使用自建zabbix平台对公司某业务系统进行了监控.近段时间 ...
- web项目的开发--第一天
如何分析需求.如何设计.编码实现.测试. 用ssm架构实现CRM项目代码编写. CRM项目: 关键是养成好的编程思想和编程习惯. 技术架构 视图层(view): 展示数据,跟用户交互. html,cs ...
- 【每日一题】【map、数组、二维数组排序、静态函数和库函数】2022年2月24日-NC97 字符串出现次数的TopK问题
描述给定一个字符串数组,再给定整数 k ,请返回出现次数前k名的字符串和对应的次数.返回的答案应该按字符串出现频率由高到低排序.如果不同的字符串有相同出现频率,按字典序排序.对于两个字符串,大小关系取 ...
- PAM8403 3.3V音频功放调试笔记
做I2S输出用了PT8211(实际上买到的丝印是GH8211), 双声道, LSB格式, 工作正常但是输出功率非常低, 喇叭声音要贴近了才能勉强听到, 所以打算做一个PT8211带功放的I2S模块. ...
- 解决Win10更新后远程桌面提示CredSSP加密Oracle修正的问题
1.以管理员身份打开cmd,运行命令提示符:2.执行REG ADD HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Cre ...
- Jmeter之响应数据乱码问题
在进行接口测试时经常长出现响应结果中中文乱码问题 解决以上现象最简洁有效的方法为在测试计划下添加beanshell后置处理器 1.右击测试计划->添加->后置处理器->beanshe ...
- python 之excel文件读取封装
import os import xlrd PATH = lambda p: os.path.abspath( os.path.join(os.path.dirname(__file__), p) ) ...