Python中的网络编程之TCP

文章目录

  • Python中的网络编程之TCP
    • 1、TCP介绍
    • 2、TCP特点
    • 3、TCP与UDP的不同点
    • 4.tcp通信模型
    • 5、tcp客户端
    • 6.tcp服务器
    • 7、TCP的注意事项
    • 8.文件下载案例
    • 9. TCP的三字握手四次挥手
    • 10、TCP长/短连接
      • 1.tcp长连接和短连接
      • 2. TCP短连接
      • 3. TCP长连接
      • 4.TCP长/短连接操作过程
      • 5.TCP长/短连接的优点和缺点
      • 6.TCP长/短连接的应用场景

1、TCP介绍

TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

TCP通信需要经过创建连接、数据传送、终止连接三个步骤。

TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,“打电话”",UDP则向发送信件。

2、TCP特点

1. 面向连接

  • 通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输
  • 双方间的数据传输都可以通过这一个连接进行
  • 完成数据交换后,双方必须断开此连接,以释放系统资源。
  • 这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。

2. 可靠传输

1)TCP采用发送应答机制

TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功

2)超时重传

发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段

TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。

3)错误校验

TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

4) 流量控制和阻塞管理

流量控制用来避免主机发送得过快而使接收方来不及完全收下。

3、TCP与UDP的不同点

TCP UDP
TCP的传输是可靠传输 UDP的传输是不可靠传输。
TCP是基于连接的协议,在正式收发数据前,必须和对方建立可靠的连接。 UDP是和TCP相对应的协议,它是面向非连接的协议,它不与对方建立连接,而是直接把数据包发送出去
TCP是一种可靠的通信服务,负载相对而言比较大,TCP采用套接字(socket)或者端口(port)来建立通信。 UDP是一种不可靠的网络服务,负载比较小。
TCP和UDP结构不同,TCP包括序号、确认信号、数据偏移、控制标志(通常说的URG、ACK、PSH、RST、SYN、FIN)、窗口、校验和、紧急指针、选项等信息。 UDP包含长度和校验和信息。
TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
TCP在发送数据包前在通信双方有一个三次握手机制,确保双方准备好,在传输数据包期间,TCP会根据链路中数据流量的大小来调节传送的速率,传输时如果发现有丢包,会有严格的重传机制,故而传输速度很慢。 UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
TCP支持全双工和并发的TCP连接,提供确认、重传与拥塞控制。 UDP适用于哪些系统对性能的要求高于数据完整性的要求,需要“简短快捷”的数据交换、需要多播和广播的应用环境。

4.tcp通信模型

  • udp通信模型中,在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中,“写信"”
  • tcp通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,“打电话”"

TCP通信模型:

5、tcp客户端

所谓的服务器端:就是提供服务的一方,而客户端,就是需要被服务的一方

tcp客户端构建流程

tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多

示例代码:

from socket import *# 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)# 目的信息
server_ip = input("请输入服务器ip:")
server_port = int(input("请输入服务器port:"))# 链接服务器
tcp_client_socket.connect((server_ip, server_port))# 提示用户输入数据
send_data = input("请输入要发送的数据:")tcp_client_socket.send(send_data.encode("gbk"))# 接收对方发送过来的数据,最大接收1024个字节
recvData = tcp_client_socket.recv(1024)
print('接收到的数据为:', recvData.decode('gbk'))# 关闭套接字
tcp_client_socket.close()

6.tcp服务器

在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:

  • socket创建一个套接字
  • bind绑定ip和port
  • listen使套接字变为可以被动链接
  • accept等待客户端的链接
  • recv/send接收发送数据

一个很简单的tcp服务器如下:

from socket import *# 创建socket
tcp_server_socket = socket(AF_INET, SOCK_STREAM)# 本地信息
address = ('', 7788)# 绑定
tcp_server_socket.bind(address)# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcp_server_socket.listen(128)# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务
# client_socket用来为这个客户端服务
# tcp_server_socket就可以省下来专门等待其他新客户端的链接
client_socket, clientAddr = tcp_server_socket.accept()# 接收对方发送过来的数据
recv_data = client_socket.recv(1024)  # 接收1024个字节
print('接收到的数据为:', recv_data.decode('gbk'))# 发送一些数据到客户端
client_socket.send("thank you !".encode('gbk'))# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
client_socket.close()

7、TCP的注意事项

  • 服务器一般情况下都需要绑定端口号,否则客户端找不到这个服务器
  • tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip、port等信息就好,本地客户端可以随机
  • tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
  • 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信
  • 当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
  • listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
  • 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信
  • 关闭accept返回的套接字意味着这个客户端已经服务完毕
  • 当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线

8.文件下载案例

server:

from socket import *
import sysdef get_file_content(file_name):"""获取文件的内容"""try:with open(file_name, "rb") as f:content = f.read()return contentexcept:print("没有下载的文件:%s" % file_name)def main():if len(sys.argv) != 2:print("请按照如下方式运行:python3 xxx.py 7890")returnelse:# 运行方式为python3 xxx.py 7890port = int(sys.argv[1])# 创建sockettcp_server_socket = socket(AF_INET, SOCK_STREAM)# 本地信息address = ('', port)# 绑定本地信息tcp_server_socket.bind(address)# 将主动套接字变为被动套接字tcp_server_socket.listen(128)while True:# 等待客户端的链接,即为这个客户端发送文件client_socket, clientAddr = tcp_server_socket.accept()# 接收对方发送过来的数据recv_data = client_socket.recv(1024)  # 接收1024个字节file_name = recv_data.decode("utf-8")print("对方请求下载的文件名为:%s" % file_name)file_content = get_file_content(file_name)# 发送文件的数据给客户端# 因为获取打开文件时是以rb方式打开,所以file_content中的数据已经是二进制的格式,因此不需要encode编码if file_content:client_socket.send(file_content)# 关闭这个套接字client_socket.close()# 关闭监听套接字tcp_server_socket.close()if __name__ == "__main__":main()

client:

from socket import *def main():# 创建sockettcp_client_socket = socket(AF_INET, SOCK_STREAM)# 目的信息server_ip = input("请输入服务器ip:")server_port = int(input("请输入服务器port:"))# 链接服务器tcp_client_socket.connect((server_ip, server_port))# 输入需要下载的文件名file_name = input("请输入要下载的文件名:")# 发送文件下载请求tcp_client_socket.send(file_name.encode("utf-8"))# 接收对方发送过来的数据,最大接收1024个字节(1K)recv_data = tcp_client_socket.recv(1024)# print('接收到的数据为:', recv_data.decode('utf-8'))# 如果接收到数据再创建文件,否则不创建if recv_data:with open("[接收]"+file_name, "wb") as f:f.write(recv_data)# 关闭套接字tcp_client_socket.close()if __name__ == "__main__":main()

9. TCP的三字握手四次挥手

Linux模块详解TCP

10、TCP长/短连接

1.tcp长连接和短连接

  • TCP在真正的读写操作之前,server与client之间必须建立一个连接
  • 当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,
  • 连接的建立通过三次握手,释放则需要四次握手
  • 所以说每个连接的建立都是需要资源消耗和时间消耗的。

2. TCP短连接

模拟一种TCP短连接的情况:

  1. client 向 server 发起连接请求
  2. server 接到请求,双方建立连接
  3. client 向 server 发送消息
  4. server 回应 client
  5. 一次读写完成,此时双方任何一个都可以发起 close 操作

在步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。

从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!

3. TCP长连接

再模拟一种长连接的情况:

  1. client 向 server 发起连接
  2. server 接到请求,双方建立连接
  3. client 向 server 发送消息server 回应 client
  4. 一次读写完成,连接不关闭
  5. 后续读写操作…
  6. 长时间操作之后client发起关闭请求

4.TCP长/短连接操作过程

4.1 短连接的操作步骤是:

建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接

4.2 长连接的操作步骤是:
建立连接——数据传输…(保持连接)…数据传输——关闭连接

5.TCP长/短连接的优点和缺点

  • 长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
  • 对于频繁请求资源的客户来说,较适用长连接。
  • client与server之间的连接如果一直不关闭的话,会存在一个问题,
  • 随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,
  • 如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;
  • 如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。
  • 短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。
  • 但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

6.TCP长/短连接的应用场景

  • 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
  • 每个TCP连接都需要三次握手,这需要时间,如果每个操作都是先连接,
  • 再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,
  • 再次处理时直接发送数据包就OK了,不用建立TCP连接。
  • 例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误
  • 而且频繁的socket 创建也是对资源的浪费。
  • 而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,
  • 而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,
  • 如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,
  • 那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

Python中的网络编程之TCP相关推荐

  1. Python中的网络编程之UDP

    Python中的网络编程之UDP 文章目录 Python中的网络编程之UDP 一.Socket编程 `1.什么是客户端/服务器架构`? **`2.套接字:通信端点`** 3.套接字地址:主机-端口对 ...

  2. java网络编程之TCP通讯

    java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, 1 /* 2 *TCP 3 *建立连接,形成传输数据的通道: 4 *在连接中进行大数据量传输: ...

  3. Python之路 - 网络编程之Socket

    Python之路 - 网络编程之Socket C/S架构 ? Socket ? 基于TCP ? 基于UDP ? Socket对象方法 ? C/S架构 ? 在网络通信中 , 一般是一方求一方应 , 求的 ...

  4. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. J ...

  5. 【Python基础】网络编程之IP地址

    [Python基础]网络编程之IP地址 文章目录 IP 地址的介绍 1. IP 地址的概念 2. IP 地址的表现形式 2. IP 地址的作用 3. 查看 IP 地址 4. 检查网络是否正常 3. 小 ...

  6. Centos网络编程之tcp十一种状态及问题处理办法

    尊重原创版权: https://www.noveljp.com/hot/43730.html 更多内容参考: https://www.noveljp.com/ Linux网络编程之tcp十一种状态及问 ...

  7. 网络编程之TCP协议与UDP对比

    网络编程之TCP协议与UDP对比 UDP协议: 1,面向无连接. 2,不可靠协议,容易丢包. 3,速度快. 4,包体积有限制,64k以内. 通常,聊天,在线视频,凌波. TCP协议: 1.面向连接. ...

  8. Linux网络编程之TCP状态转移

    Linux网络编程之TCP状态转移 一.TCP状态转移时序 二.半关闭及shutdown函数 一.TCP状态转移时序 TCP状态转移图: netstat -apn | grep client 查看客户 ...

  9. java 网络编程简单聊天_网络编程之 TCP 实现简单聊天

    网络编程之 TCP 实现简单聊天 客户端 1.连接服务器 Socket 2.发送消息 package lesson02;import java.io.IOException;import java.i ...

最新文章

  1. shell算数表达式运算
  2. ASP.NET MVC Action向视图传值之匿名类型
  3. python中的排序方法都有哪些_Python中的排序方法sort(),sorted(),argsort()等
  4. K8S+Docker理论与实践深度集成
  5. php 安装rabtmq amqp 扩展
  6. java.lang.IllegalStateException: Not connected to server
  7. linux libstdc 怎样升级,linux 更新libstdc++.so.6
  8. adb 连接时候不弹出授权对话框
  9. STC12参考例程(附模块资料代码注释、学习经验总结)
  10. 一、Geos库的安装和计算多边形是否相交
  11. mysql mysql.sock连接_【MySQL】mysql.sock文件作用
  12. Stanford CoreNLP 纯Python版本的深度学习NLP工具包 stanza 使用笔记
  13. unity 下载文件到存放本地
  14. cocos2d_lua 2.5D
  15. 游戏安全逆向工程师:从入门到精通83课分享
  16. excel锁定单元格不能修改_【软件应用】工程中经常运用的Excel技巧(附教程下载)...
  17. OpenHarmony社区开源代码下载及编译
  18. 114搜索引擎跃居网络“十大流氓软件”之首
  19. java poi 解析et,POI操作WPS表格
  20. 【重识云原生】第四章云网络4.3.10.5节——VXlan组网架构

热门文章

  1. 八月25日8点半服务器维修,三国乱世8月25日合区维护公告
  2. 初一七年级计算机信息全册教案,初一信息技术教案全一册
  3. 200908阶段一C++多态
  4. ERROR: Could not read unit serial number!
  5. Kebernetes 学习总结(9)认证-授权-RBAC
  6. RabbitMQ消息可靠性分析和应用
  7. ALV打印不显示打印界面的问题
  8. 从事UNIX/LInux服务器编程最方便的代码编译工具------(eclipse for c/c++)、(FileZilla)、(Secure CRT) 这三种一定要一起使用 之3...
  9. 在 JQuery Mobile 中实现瀑布流图库布局
  10. 实现对现有的aspx请求进行异步队列控制处理