TCP 简介:

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

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

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

TCP 特点:

  • 面向连接:
    通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输;
    双方间的数据传输都可以通过这一个连接进行;
    完成数据交换后,双方必须断开此连接,以释放系统资源;
    这种连接是一对一的,因此 TCP 不适用于广播的应用程序,基于广播的应用程序请使用 UDP 协议;
  • 可靠传输
    1)、TCP 采用发送应答机制:
    TCP 发送的每个报文段都必须得到接收方的应答才认为这个 TCP 报文段传输成功;
    2)、超时重传:
    发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。
    TCP 为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
    3)、错误校验:
    TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

 

TCP 通信服务端:

创建一个 TCP 通信服务端的步骤:

1、创建一个套接字(socket)

2、绑定 ip 地址和端口(bind)

3、开启监听,让套接字变成可连接状态(listen)

4、等待客户端连接(accept)

5、接收和发送数据(recv/send)

6、关闭套接字(close)

# 导入 socket 模块
import socket

# 1、创建一个用于监听的 socket
# 参数1 表示地址族,AF_INET 表示用于 internet 进程间通信;
# 参数2 表示套接字类型,SOCK_STREAM 表示流式套接字,用于 TCP 通信;
listenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 指定服务端 ip 地址和端口(以元祖形式)
# 如果不写 ip 地址,表示本地任意一个地址
servAddr = ("", 8889)

# 2、绑定地址和端口
listenSocket.bind(servAddr)

# 3、开启监听,由主动套接字变成被动套接字,
# 即让套接字处于可被动连接状态;
# 参数 10 表示同一时间最多允许 10 个客户端连接;
listenSocket.listen(10)

# 4、等待客户端连接:
# 如果客户端连接成功,则返回一个专门用于通信的套接字,
# 监听套接字就可以省下来,继续等待其他客户端的连接了;
# 还会返回客户端的 ip 地址和端口号;
connSocket, clientAddr = listenSocket.accept()
print("客户端地址信息:", clientAddr)

# 5、接收客户端发送的数据:1024 表示最大接收的字节数
recvData = connSocket.recv(1024)
print("客户端发送的数据:", recvData.decode("UTF-8"))

# 6、发送数据到客户端
connSocket.send("I am fine, thank you!".encode("UTF-8"))

# 7、关闭套接字
connSocket.close()  # 关闭通信套接字,则不能与客户端继续通信了
listenSocket.close()# 关闭监听套接字,则不能再监听客户端的连接了

 

TCP 通信客户端:

创建一个 TCP 客户端的步骤:

1、创建一个套接字

2、指定服务器的 ip 地址和端口

3、连接到服务器

4、发送和接收数据

5、关闭套接字

# 导入 socket 模块
import socket

# 1、创建 socket
tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2、指定服务端的 ip 地址和端口
servAddr = ("127.0.0.1", 8889)

# 3、连接到服务器
tcpSocket.connect(servAddr)

# 4、发送数据到服务器
tcpSocket.send("how are you!".encode("UTF-8"))

# 5、接收服务器返回的数据
recvData = tcpSocket.recv(1024)
print("服务器返回的数据:", recvData.decode("UTF-8"))

# 6、关闭套接字
tcpSocket.close()