TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向链接的、可靠的、基于字节流的传输层通讯协议,由IETF的RFC 793定义。服务器
TCP通讯须要通过建立链接、数据传送、终止链接三个步骤。socket
TCP通讯是面向链接而且可靠的。通讯双方在正式进行通讯以前必须先创建可靠一对一的链接,而且分配必定的系统内核资源,双发的数据经过这个链接进行,并且当通讯结束以后双发必须断开链接以释放系统资源。tcp
TCP采用发送应答机制,每次传输的成功都依赖于发送和回应。若是在必定时间没有收到回应,则会进行重发。而且为了避免丢包,每一个数据包中都有一个序号,同时序号也保证了传送到接收端实体的包的按序接收。spa
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()
复制代码
from socket import *
# 建立socket
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
# 本地信息
address = ('', 7890)
# 绑定
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()
复制代码
当客户端要跟服务端通讯的时候会经过三次握手来进行资源的准备。code
下文中的SYN和ACK是为了区分请求(SYN)和应答(ACK)。J、K仅表明随机标识,实际并不会发送J、K。cdn
首先客户端发起请求并将带有带有一个随机标记SYN J的数据包给服务端。为了标记响应在前面添加SYN。server
服务端接受到以后,revc会解堵塞,并分配一个新的套接字来对数据进行收发。因为TCP要求每次请求都要有一次应答,因此服务端将客户端发送过来的随机标记加一 J+1发送给客户端告诉它服务端已经准备好资源了。为了标记响应在前面添加ACK。blog
此时服务端也须要确认客户端是不是可靠的,同时客户端也须要进行资源准备,因此服务端会向客户端发送一个一样带有随机标记的数据包(SYN K)。ip
当客户端收到服务端的包的时候也须要给服务端发送确认的包,因此把服务端发送过来的K加一将(ACK K+1)发送给服务端。资源
因为服务器应答和服务器确认客户端都是发往客户端的,而且中间不会有延时或者不发的状况,因此服务端确认客户端的包就跟服务端相应客户端链接的包一块儿发送给客户端了。两步合为一步,因此叫三次握手。
当这三次握手完成以后双方便确认对方是可靠的,就能够进行通讯了。
当客户端和服务端双方通讯结束的时候,为了保证系统资源的释放,双方须要经过四次挥手来断开链接,释放资源。因为套接字socket是全双工的,也就是收发能够同时进行,因此当关闭一个套接字的时候须要关闭发送和接收两个通道。
数据包的发送同三次握手同样一样会发送一个随机标记,在响应的时候对其进行加一操做。
断开链接一般也是由客户端首先发起的,当客户端的socket调用close关闭链接的时候会发送数据包给服务端。
服务端收到客户端的数据包的时候会回复给客户端一个数据包,表示确认收到客户端关闭链接的请求。
服务端的recv解堵塞,当服务端的套接字调用close的时候会给客户端发送一个数据包通知客户端将要关闭发送。可是此时服务端会保留资源,直到收到客户端的确认包。
当客户端接收到数据包的时候再给服务端发送确认包,此时客户端的资源也会被保留一段时间。
正常状况下,客户端和服务端都会收到两次响应,从而关闭socket的收发两个通道。
服务端资源保留是由于若是到服务端TCP数据包发送的超时时间尚未收到客户端的回应,那么会再次给客户端发送数据包。而客户端资源保留也是由于若是服务端没有收到数据包的时候回再次发送过来数据,因此须要进行接收。若是是客户端发起的关闭请求,那么客户端的资源一般会保留2msl也就是接受两次数据包的时间,增长接收到服务端重发数据包的几率,若是过期也会关闭套接字释放资源。
四次挥手中服务端发送给客户端的关闭请求的响应和给客户端发送确认关闭的数据包,没有像三次握手那样合为一块儿,是由于服务端调用close的时机不肯定,而若是是客户端先发起的close,那么客户端就要等待两倍的数据包发送时长。服务端是绑定端口的,若是没有释放资源是不能再次进行服务的,而客户端是随机端口的,不会受此限制。
经过TCP进行通讯的时候首先经过三次握手准备资源,而后进行通讯。通讯过程也是有来有回的,每次请求都会对应一次响应。当通讯结束的时候,会经过四次挥手关闭链接,释放系统资源。