<1>TCP概念
英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议.
<2>TCP特点
1、 面向连接
TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。这种连接是一对一的。
2.、可靠传输
TCP采用发送应答机制:TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功
3、超时重传
发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。
4、错误校验
由发送端计算,然后由接收端验证,其目的是为了检测数据在发送端到接收端之间是否有改动,如果接收方检测到校验和有差错,则直接丢弃这个数据包。
5、流量控制和阻塞管理
流量控制用来避免主机发送得过快而使接收方来不及完全收下。
<3>TCP的优缺点
优点:可靠,稳定、适合传输大量数据。
缺点:传输速度较udp慢、占用系统资源高。
<4>TCP和UDP区别
tcp | udp |
---|---|
TCP面向连接 | UDP是不面向连接 |
TCP提供可靠的数据传输 | UDP不保证可靠的数据传输,容易出现丢包情况 |
TCP需要连接传输速度慢 | UDP不需要连接传输速度快 |
TCP不支持发广播 | UDP支持发广播 |
TCP对系统资源要求较多 | UDP对系统资源要求较少 |
TCP适合发送大量数据 | UDP适合发送少量数据 |
TCP有流量控制 | UDP没有流量控制 |
<5>TCP使用场景
当对网络通讯质量有要求的时候
<6>TCP客户端
所谓的客户端,就是需要被服务的一方,而服务器端就是提供服务的一方.
<7>TCP服务器
完成一个tcp服务器的功能,需要的流程如下:
(1)socket创建一个套接字
(2)bind绑定ip和port
(3)listen使套接字变为可以被动链接
(4)accept等待客户端的链接
(5)recv/send接收发送数据
<8>TCP的注意点
1、tcp服务器一般情况下都需要绑定端口号,否则客户端找不到这个服务器
2、tcp客户端一般不绑定端口号,使用随机生成的端口号即可
3、tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
4、当tcp客户端和服务端建立好连接才可以收发数据,udp是不需要建立连接,直接就可以发送数据
5、当一个tcp客户端和服务端连接成功后,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
6、listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
7、关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
8、关闭accept返回的套接字意味着这个客户端已经服务完毕
9、当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线
10、tcp服务端绑定端口号,程序退出后端口号不会立即释放,解决办法可以设置socket选项,让程序退出端口号立即释放,也称为端口号复用
<补充>判断文件是否存在
import os -> os.path.exists(“文件名”)
<9>TCP的三次握手(建立连接时)
1、符号
(1)SYN: 表示连接请求
(2)ACK: 表示确认
(3)FIN: 表示关闭连接
(4)seq:表示报文序号
(5)ack: 表示确认序号
2、含义:
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack (number )=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
<10>TCP的4次挥手(断开连接时)
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送。
(4)第四次挥手:Client收到FIN后,接着发送一个ACK给Server,确认序号为收到序号+1。
等待1-2分钟,没有收到服务端的关闭请求,才真正关闭
<11>wireshark抓包工具使用
1、通过interface List -> 获取交互列表
2、通过ip地址找到对应的那个点击start选项,然后会显示捕获的数据列表
3、.在Fileter中输入过滤条件 3.在Fileter中输入过滤条件
4、点击任意一行获取详细信息
<12>文件下载器——示例代码
1、客户端
import socket
if __name__ == '__main__':
# 创建tcp客户端套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 和服务端应用程序建立连接
tcp_client_socket.connect(("192.168.14.99", 8080))
# 发送下载文件的请求
file_name = input("请输入您要下载的文件名:")
file_name_data = file_name.encode("utf-8")
# 发送请求数据
tcp_client_socket.send(file_name_data)
# 把数据写入到下载文件里面
with open("/home/python/Desktop/" + file_name, "wb") as file:
while True:
# 循环接收服务端发送的文件数据
file_data = tcp_client_socket.recv(1024)
if file_data:
file.write(file_data)
else:
print("服务端把数据发送完成并关闭连接了")
break
# 关闭客户端套接字
tcp_client_socket.close()
2、服务端
import socket
import os
if __name__ == '__main__':
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定端口号
tcp_server_socket.bind(("", 8080))
# 设置监听,把主动套接字变成被动套接字,服务端套接字只负责接收客户端的连接请求
tcp_server_socket.listen(128)
# 循环调用accept可以支持多个客户端连接服务端,但是不能同时多个客户端连接服务器端,因为是同步下载的
# 一个客户端下载完成以后另外一个客户端才能和服务端建立连接下载对应的文件
while True:
# 等待接收客户端的连接请求
service_client_socket, ip_port = tcp_server_socket.accept()
print("客户端连接成功了:", ip_port)
# 接收客户端的请求信息
file_name_data = service_client_socket.recv(1024)
# 对二进制数据进行解码
file_name = file_name_data.decode("utf-8")
# 判断文件是否存在
if os.path.exists(file_name):
# 文件存在
# 打开文件, with open 关闭文件操作不需要程序员自己去做,有系统去做
with open(file_name, "rb") as file:
# 读取文件数据
while True:
# 循环读取文件数据
file_data = file.read(1024)
if file_data:
# 表示读到数据,然后把数据发送给客户端
service_client_socket.send(file_data)
else:
print("请求的文件数据发送完成")
break
else:
print("下载的文件服务器不存在")
# 终止和这个客户端服务
service_client_socket.close()
# 终止客户端连接请求服务, 服务端的套接字可以不用关闭
tcp_server_socket.close()