python网络-Socket之TCP编程(26)
一、TCP简介
1、TCP介绍
TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话"。
2、TCP面向连接
通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。
双方间的数据传输都可以通过这一个连接进行。
完成数据交换后,双方必须断开此连接,以释放系统资源。
这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。
3、TCP可靠传输
1)TCP采用发送应答机制
TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功
2)超时重传
发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
3)错误校验
TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
4) 流量控制和阻塞管理
流量控制用来避免主机发送得过快而使接收方来不及完全收下。
4、TCP与UDP的不同点
- 面向连接(确认有创建三方交握,连接已创建才作传输。)
- 有序数据传输
- 重发丢失的数据包
- 舍弃重复的数据包
- 无差错的数据传输
- 阻塞/流量控制
二、TCP数据包格式
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个数据包。
那么我们就先来看一下TCP数据包的格式:
- 在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG.
- URG—为1表示高优先级数据包,紧急指针字段有效。
- ACK—为1表示确认号字段有效
- PSH—为1表示是带有PUSH标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
- RST—为1表示出现严重差错。可能需要重现创建TCP连接。还可以用于拒绝非法的报文段和拒绝连接请求。
- SYN—为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步
- FIN—为1表示发送方没有数据要传输了,要求释放连接,
- Seq---序号,这是为了连接以后传送数据用的,
- Ack---确认号对收到的数据包的确认,值是等待接收的数据包的序列号+1。
三、TCP的三次握手
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
三次握手示意图
第一次握手:(Client向Server发送联机请求)
SYN=1(Client向Server发送联机请求)
Client想要与Server进行TCP通信,首先他需要向Server发送一个SYN=1的同步序列编号(syncsynchronized squsequence number)用来表示建立连接,并且随机产生一个数Seq number = X的数据包到Server,Server由于SYN=1知道,Client要求建立联机,到这里第一次握手就结束了
第二次握手:(Server向Client回复联机并确认联机信息)
SYN=1(Server接受Client的联机请求)
ACK=1(确认信息)
这是对第一次握手信息的确认,表示Server收到了Client的第一次握手信息
Ack=X+1(确认回复)
同时Server回复Client一个确认码Ack表示你的联机请求我已经收到,而且数据没有丢失,怎么验证数据没有丢失呢?即Ack的值等于Client发过来Seq的值加1,即Ack = X+1。因为我都知道你发过来的Seq的值,所以这个数据包没有丢失。
Seq = Y(第二次握手的数据包序列号)
Server给Client的数据包序列号,为了数据包在到达Client之后的验证,所以这次从Server到Client的数据包中同样也会随机产生一个Seq number = Y,
第三次握手
ACK=1(对第二次握手的确认)
首先Client会打开Server发送过来的Ack验证一下是否正确为Seq+1,即第一次发送的seq number+1,确认无误后,Client仍然需要给Server再次回复确认即ACK=1
Seq=Z(第三次握手的数据包序列号)
Ack=Y+1
Client告诉Server,你给我回复的信息我也收到了,怎么确定我收到了你的信息呢?就是通过Ack等于第二次握手传递过来的Seq值+1。到此为止三次握手结束进入ESTABLISHED状态,开始进行数据传输。
四、TCP四次挥手
第一次挥手发送FIN请求,第一次挥手结束。
第二次挥手开始,被动方向主动方发送ACK确认码,到这里第二次挥手结束。
第三次握手开始被动方向主动方发送FIN号结束。
第四次挥手开始主动方向被动方发送ACK确认,等待2MSL后断开TCP连接。
五、TCP的十种状态
这十种状态分别是三次握手和四次挥手中的状态,在上面两个图中都给大家标记出来了,这里再给大家一个简单的图表示
六、TCP的2MSL问题
在四次挥手中我们提到了时间等待状态,等待的时间是2MSL。
2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,
当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次挥手完成后发送了第四次挥手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个 ACK包对方没收到,那么对方在超时后将重发第三次挥手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置 SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。
七、TCP长连接和短连接
TCP在真正的读写操作之前,server与client之间必须建立一个连接,
当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,
连接的建立通过三次握手,释放则需要四次握手,
所以说每个连接的建立都是需要资源消耗和时间消耗的。
1. TCP短连接
模拟一种TCP短连接的情况:
- client 向 server 发起连接请求
- server 接到请求,双方建立连接
- client 向 server 发送消息
- server 回应 client
- 一次读写完成,此时双方任何一个都可以发起 close 操作
在第 步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!
2. TCP长连接
再模拟一种长连接的情况:
- client 向 server 发起连接
- server 接到请求,双方建立连接
- client 向 server 发送消息
- server 回应 client
- 一次读写完成,连接不关闭
- 后续读写操作...
- 长时间操作之后client发起关闭请求
3. TCP长/短连接操作过程
(1)短连接的操作步骤是:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
(2) 长连接的操作步骤是:建立连接——数据传输...(保持连接)...数据传输——关闭连接
4. TCP长/短连接的优点和缺点
长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。
client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。
- 短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。
5. TCP长/短连接的应用场景
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三次握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,再次处理时直接发送数据包就OK了,不用建立TCP连接。
例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
八、TCP的通信模型
tcp通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话"
生活中的电话机,如果想让别人能更够打通咱们的电话获取相应服务的话,需要做一下几件事情:
- 买个手机
- 插上手机卡
- 设计手机为正常接听状态(即能够响铃)
- 静静的等着别人拨打
tcp服务器如同上面的电话机过程一样,在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:
- 创建一个socket套接字
- bind绑定ip和port
- listen使套接字变为可以被动链接
- accept等待客户端的链接
- recv/send接收发送数据
九、TCP服务器代码实现
- #coding = utf-8
- from socket import *
- #1、创建socket套接字
- tcpServerSocket = socket(AF_INET,SOCK_STREAM)
- #2、绑定本地信息
- address = ("",7788)
- tcpServerSocket.bind(address)
- #3、使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动,这样就可以等着别人链接了
- tcpServerSocket.listen(5)
- """
- 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
- newSocket用来为这个客户端服务
- tcpServerSocket就可以省下来专门等待其他的客户端的链接
- """
- newSocket,clientAddress = tcpServerSocket.accept()
- #4、接收对象发送过来的数据,最大接收1024个字节
- reveiveData = newSocket.recv(1024)
- print("接收的数据为:%s"%reveiveData.decode())
- #5、发送数据到客户端
- newSocket.send("haha".encode())
- #6、关闭为这个客户端服务的套接字
- newSocket.close()
- #7、关闭监听套接字
- tcpServerSocket.close()
运行流程
1、TCP服务器
2、网络调试助手:
十、TCP客户端代码实现
所谓的服务器端:就是提供服务的一方,而客户端,就是需要被服务的一方
tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多
- #coding = utf-8
- from socket import *
- #1、创建socket
- tcpClientSocket = socket(AF_INET,SOCK_STREAM)
- #2、链接服务器
- serverAddress = ("192.168.100.106",7788)
- tcpClientSocket.connect(serverAddress)
- #3、向服务器发送数据
- tcpClientSocket.send("哈哈".encode("gb2312"))
- #4、接收对方发送过来的数据,最大接收1024个字节
- receiveData = tcpClientSocket.recv(1024)
- print("接收到的数据为%s"%receiveData.decode("gb2312"))
- #5、关闭套接字
- tcpClientSocket.close()
运行流程:
1、tcp客户端
2、网络调试助手:
python网络-Socket之TCP编程(26)的更多相关文章
- [Python] 网络编程之TCP编程
转自:TCP编程 - 廖雪峰的官方网站 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协 ...
- python网络-Socket之udp编程(24)
一.udp简介 udp --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议. udp不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地. udp在 ...
- 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
- 网络编程之TCP编程
网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...
- 【Socket编程】通过Socket实现TCP编程
通过Socket实现TCP编程 Socket通信 : 1.TCP协议是面向对象连接.可靠的.有序的,以字节流的方式发送数据. 2.基于TCP协议实现网络通信的类: 客户端----Socket类 服务器 ...
- Python网络socket学习
Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...
- JAVA 通过 Socket 实现 TCP 编程
简介 TCP简介 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机 ...
- 通过Socket实现TCP编程,用户登录之服务器相应客户端,客户端和服务端之间的通信
服务器端: 1.创建ServerSocket对象,绑定监听端口: 2.通过accept()方法监听客户端请求: 3.建立连接后通过输入流读取客户端发送的请求信息; 4.通过输出流向客户端发送响应信息; ...
随机推荐
- Linux —— shell认识与基础命令
shell 基础 shell路径: /etc/shells 系统shell版本: $SHELL 在父shell中可以调用子shell echo 把指定内容输出到屏幕上 操作选项: -e: 支持反斜杠控 ...
- HDU-1845-Jimmy's Assignment
链接:https://vjudge.net/problem/HDU-1845 题意: 给一个有向图,求最大匹配. 思路: 有相图的最大匹配,可以通过加上反向边, 求这个无向图的最大匹配, 原图的最大匹 ...
- openSUSE 跨版本升级
准备工作 此方法通过网络跨版本升级,适合 Leap 升级到下一个发行版(如 42.2 升级到 42.3),也适合 Leap 升级为 Tumbleweed.首先必须确定升级的时候有足够的时间.靠谱的更新 ...
- 机器学习框架ML.NET学习笔记【7】人物图片颜值判断
一.概述 这次要解决的问题是输入一张照片,输出人物的颜值数据. 学习样本来源于华南理工大学发布的SCUT-FBP5500数据集,数据集包括 5500 人,每人按颜值魅力打分,分值在 1 到 5 分之间 ...
- Css+Html
CSS样式 <style type="text/css"> tt.tt1 { <style type="text/css"> p { b ...
- marquee标签(跑马灯)
- I/O流操做总结(三)
说实话,其实我并不是很喜欢Java这门语言,尽管它很强大,有很多现成的API可以调用 但我总感觉它把简单的事情弄得太过复杂,甚至有时候会让人迷失 弄不清到底是为了写出东西,还是为了语言本身 我学习的第 ...
- 1.2 the structure of a compiler
Compiler 1.2 the structure of a compiler Compiler : analysis and synthesis syntactically 语法上的 sema ...
- 解决首次在eclipse中使用maven构建hadoop等项目时报Missing artifact sun.jdk:tools:jar:1.5.0的问题
问题原因: eclipse中的maven插件默认没有引用环境变量,所以找不到jdk的路径,也就找不到tool.jar. 解决办法: 步骤如下: 1.关闭eclips 2.在eclipse的解压目录中与 ...
- C语言的time函数和localtime函数
1.获取当前时间,并获取当前时间(即系统时间)距离1970年1月1日的时间间隔,以秒为单位. 2.获取指定时间距离1970年1月1日的时间间隔,以秒为单位.