TCP协议与基于tcp协议的套接字socket
一、TCP协议(流式协议)
1、可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。数据传输以数据流的形式传送
2.(1)三次握手建链接
(2)四次挥手断开链接
(3)tcp协议的状态
(4)syn洪水攻击与半连接池
3、(1)三次握手建立链接、四次挥手断开链接(各种状态)
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
PSH(push传送)
FIN(finish结束)
RST(reset重置)
URG(urgent紧急)
三次握手 —— TCP协议提供可靠的连接服务,采用三次握手建立一个连接
第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECD状态。
第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
四次挥手 —— TCP采用四次挥手关闭连接
第一次挥手:客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送,客户端A进入FIN_WAIT_1状态
第二次挥手:服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。服务端B进入CLOSE_WAIT状态
第三次挥手:服务端数据发送完毕以后,服务器B关闭与客户端A的连接,发送一个FIN给客户端A,服务端进入进入LAST_ACK状态
第四次挥手:客户端A收到FIN后进入TIME_WAIT状态,接着发送一个ACK给服务端,确认序号为收到序号+1,服务端B进入CLOSED状态,完成四次挥手
# 1.什么是三次握手,四次挥手 # 2.为什么建立连接是三次握手,而关闭连接却是四次挥手呢? 这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。 # 3.为什么不能用两次握手进行连接? 三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。 现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
(2)syn洪水攻击
syn洪水攻击:syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
(3)半连接池
半连接: 在三次握手过程中,服务端发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect),此时服务端处于SYN_RCVD状态
半连接池(服务端)backlog:客户端每来一个请求,就会存放到半连接池。半连接池固定大小,只允许一定数量请求进入
二、基于tcp协议的套接字socket
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
1、socket层
2、什么是socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。Socket是封装好TCP/IP协议的接口。
3、socket工作流程
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
from socket import socket, AF_INET, SOCK_STREAM IP = '127.0.0.1' PORT = 8888 ADDRESS = (IP, PORT) BUFSIZE = 1024 # 1.创建一个服务端对象(AF_INET:IPv4,SOCK_STREAM:sock流) ser_socket = socket(AF_INET, SOCK_STREAM) # 2.绑定服务器的IP地址,端口() ser_socket.bind(ADDRESS) # 3.设置半连接池,限制请求的个数 ser_socket.listen(5) # 4.等待客户端请求 cli_socket, cli_adrr = ser_socket.accept() print(cli_socket) print(cli_adrr) # 5.收发数据 data = cli_socket.recv(BUFSIZE) print(data.decode('utf-8')) cli_socket.send('服务器已接收到数据'.encode('utf-8')) # 只能以字节类型发送 # 6.关闭与客户端的连接 cli_socket.close() # 7.关闭服务器(一般不会关闭服务器) # ser_socket.close()
from socket import socket, AF_INET, SOCK_STREAM IP = '127.0.0.1' PORT = 8888 ADDRESS = (IP, PORT) BUFSIZE = 1024 # 1.创建客户端socket对象 cli_socket = socket(AF_INET, SOCK_STREAM) # 2.连接服务器 cli_socket.connect(ADDRESS) # 3.发收数据 cli_socket.send('hello'.encode('utf-8')) # 只能以字节类型发送 data = cli_socket.recv(BUFSIZE) print(data.decode('utf-8')) # 关闭客户端连接 cli_socket.close()
三、补充
例如:https://www.cnblogs.com/linagcheng/p/9556260.html
(1)https :表示服务器协议
(2)www.cnblogs.com :表示域名,当访问服务器是,会通过DNS将域名解析为IP地址,然后通过IP地址访问服务器
- 它有默认端口号:80 ======>www.cnblogs.com:80
(3)/linagcheng/p/9556260.html :表示服务器上的文件