TCP协议
TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。
TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话""
TCP特点:
1. 面向连接
通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。
双方间的数据传输都可以通过这一个连接进行。
完成数据交换后,双方必须断开此连接,以释放系统资源。
这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。
2. 可靠传输
1)TCP采用发送应答机制
TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功
2)超时重传
发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。
TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
3)错误校验
TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
4) 流量控制和阻塞管理
流量控制用来避免主机发送得过快而使接收方来不及完全收下。
TCP与UDP的不同点
- 面向连接(确认有创建三方交握,连接已创建才作传输。)
- 有序数据传输
- 重发丢失的数据包
- 舍弃重复的数据包
- 无差错的数据传输
- 阻塞/流量控制
TCP通信模型
tcp通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话""
tcp客户端发送、接收数据
tcp客户端连接服务器后,可以发送数据到服务器端,也可以接收服务器端返回的数据
import socket
# 创建套接字对象
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务端
tcp_socket.connect(("192.168.99.57", 8080))
# 循环输入信息
while True:
send_data = input("请输入发送的信息:\n")
# 输入不会空进行发送和接收 为空 结束循环
if send_data:
# 发送信息
tcp_socket.send(send_data.encode())
# 接受信息
recv_data = tcp_socket.recv(1024)
print("[新消息来了]192.168.99.57:\n", recv_data.decode())
else:
break
# 断开连接
tcp_socket.close()
tcp服务器端
创建流程如下:
- socket创建一个套接字
- bind绑定ip和port
- listen使套接字变为可以被动链接
- accept等待客户端的链接
- recv/send接收发送数据
import socket
"""
socket创建一个套接字
bind绑定ip和port
listen使套接字变为可以被动链接
accept等待客户端的链接
recv/send接收发送数据
"""
# 创建套接字对象 在tcp服务端是掌控连接 不掌控传输
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定端口
addr = ('', 8080)
tcp_socket.bind(addr)
# 设置监听,最多可连接数
# tcp_socket由主动连接变成被动连接
tcp_socket.listen(128)
# 可以多个客户端连接
while True:
# 等待连接
# 返回值是元组,有两个元素
# 第一个是socket对象 每个连接都有一个socket对象 掌控数据传输
# 第二个是客户端的ip和端口
send_socket, send_port = tcp_socket.accept()
print("已经连接客户端:", send_port)
# 可以多次接受发送信息
while True:
# 接受信息
recv_content = send_socket.recv(1024)
if recv_content:
print("[新消息来了]%s:\n%s" % (send_port, recv_content.decode()))
# 发送信息
content = input("请输入回复内容:\n")
send_content = send_socket.send(content.encode())
else:
print("客户端可能断开了")
break
# 关闭当前客户端连接
send_socket.close()
# 关闭连接,此时关闭的连接是:禁止新的客户端连接 已经连接的客户端可以继续使用
# tcp_socket.close()