TCP通信流程以及一些TCP的相关概念

1.TCP和UDP区别

都为传输层协议
UDP:用户数据报协议,面向无连接,可以单播,多播,广播,面向数据报,不可靠
TCP:传输控制协议,面向连接的,可靠的,基于字节流,仅支持单播传输

UDP TCP
是否创建连接 无连接 面向连接
是否可靠 不可靠 可靠的
连接的对象个数 一对一、一对多、多对一、多对多 一对一
传输的方式 面向数据报 面向字节流
首部开销 8个字节 最少20个字节
适用场景 实时应用(视频会议,直播) 可靠性高的应用

2.TCP通信流程

(1) 服务器端
1.创建一个用于监听的套接字
      -监听:监听有客户端的连接
      -套接字:就是一个文件描述符
2.将这个监听文件描述符和本地的IP和端口绑定(IP和端口就是服务器的地址信息)
      -客户端连接服务器的时候使用的就是这个IP和端口
3.设置监听,监听的fd开始工作
4.阻塞等待,当有客户端发起连接,解除阻塞,接受客户端的连接,会得到一个和客户端通信的套接字(fd)
5.通信
      -接收数据
      -发送数据
6.通信结束,断开连接

(2) 客户端
1.创建一个用于通信的套接字(fd)
2.连接服务器,需要指定连接的服务器的IP和端口3.连接成功了,客户端可以直接和服务器通信
      -接收数据
      -发送数据
4.通信结束,断开连接

3.通信时所需要用到的函数(API)

int socket(int domain,int type,int protoco1);
	-功能:创建一个套接字
	-参数:
		- domain : 协议族
			AF_INET : ipv4 
			AF_INET6 : ipv6
			AF__UNIX,AF_LOCAL :本地套接字通信(进程间通信>
		- type : 通信过程中使用的协议类型
			SOCK_STREAM ︰流式协议
			SOCK_DGRAM︰报式协议
		-protoco1 : 具体的一个协议。一般写0
			- SOCK_STREAM︰流式协议默认使用 TCP
			- SOCK_DGRAM︰报式协议默认使用UDP
	-返回值:
		-成功:返回文件描述符,操作的就是内核缓冲区。-失败:-1

int bind(int sockfd,const struct sockaddr *addr,socklen_t addr len);
	-功能:绑定,将fd 和本地的IP +端口进行绑定
	-参数:
		- sockfd :通过socketi函数得到的文件描述符
		- addr :需要绑定的socket地址,这个地址封装了ip和端口号的信息
		- addrlen :第二个参数结构体占的内存大小

int listen(int sockfd,int backlog);  // /proc/sys/net/core/somaxconn
	-功能:监听这个socket上的连接
	-参数:
		- sockfd :通过socket()函数得到的文件描述符
		- backlog :未连接的和已经连接的和的最大值,5

int accept(int sockfd,struct sockaddr *addr ,socklen_t *addrlen);
	-功能:接收客户端连接,默认是一个阻塞的函数,阻塞等待客户端连接
	-参数:
		- sockfd :用于监听的文件描述符
		- addr :传出参数,记录了连接成功后客户端的地址信息(ip, port)
		- addrlen :指定第二个参数的对应的内存大小
	-返回值:
		-成功:用于通信的文件描述符
		- -1 :失败
int connect(int sockfd,const struct sockaddr *addr, socklen_t addrlen) ;
	-功能:客户端连接服务器
	-参数:
		- sockfd :用于通信的文件描述符
		- addr :客户端要连接的服务器的地址信息
		- addrlen :第二个参数的内存大小
	-返回值: 成功0,失败-1
ssize_t write(int fd,const void *buf,size_t count);//写数据
ssize_t read(int fd,void *buf, size_t count);//读数据

4.TCP三次握手

目的:保证双方互相之间建立了连接
什么时候三次握手:发生在客户端连接时
为甚莫要三次握手:确认双方都能发送和接收数据
三次握手在TCP协议头中1.将SYN的值置为12.服务端将ACK置为1,并且将SYN置为13.客户端将ACK置为1
序号,确认号:确保TCP协议的传输时的完整性和顺序性

第一次握手:
	1.客户端将SYN标志位置为1
	2.生成一个随机的32位的序号seq=J ,这个序号后边是可以携带数据(数据的大小)
第二次握手:
	1.服务器端接收客户端的连接:ACK=1
	2.服务器会回发一个确认序号:ack=客户端的序号+数据长度+SYN/FIN(按一个字节算)
	3.服务器端会向客户端发起连接请求:SYN=1
	4.服务器会生成一个随机序号:seq = K
第三次握手:
	1.客户单应答服务器的连接请求:ACK=1
	2.客户端回复收到了服务器端的数据:ack=服务端的序号+数据长度+SYN/FIN(按一个字节算)

5.三次握手、滑动窗口、四次挥手

# mss: Maximum Segment Size(一条数据的最大的数据量)
# win: 滑动窗口
1. 客户端向服务器发起连接,客户单的滑动窗口是4096,一次发送的最大数据量是1460
2. 服务器接收连接情况,告诉客户端服务器的窗口大小是6144,一次发送的最大数据量是1024
3. 第三次握手
4. 4-9 客户端连续给服务器发送了6k的数据,每次发送1k
5.10次,服务器告诉客户端:发送的6k数据以及接收到,存储在缓冲区中,缓冲区数据已经处理了2k,窗口大小是2k
6.11次,服务器告诉客户端:发送的6k数据以及接收到,存储在缓冲区中,缓冲区数据已经处理了4k,窗口大小是4k
7.12次,客户端给服务器发送了1k的数据

8.13次,客户端主动请求和服务器断开连接,并且给服务器发送了1k的数据
9.14次,服务器回复ACK 8194, a:同意断开连接的请求 b:告诉客户端已经接受到方才发的2k的数据c:滑动窗口2k
10.1516次,通知客户端滑动窗口的大小
11.17次,第三次挥手,服务器端给客户端发送FIN,请求断开连接
12.18次,第四次回收,客户端同意了服务器端的断开请求

6.TCP三次握手、四次挥手的状态转换

Client Server
SYN_SENT(connect()) LISTEN(listen())
SYN_RECVD
ESTABLISHED ESTABLISHED
Client Server
FIN_WAIT_1 (close()) CLOSE_WAIT
LAST_ACK(close())
FIN_WAIT_2
TIME_WAIT

主动断开连接的一方, 最后进入一个 TIME_WAIT状态, 这个状态会持续: 2msl
半关闭状态

7.端口复用

在最后的关闭时,出现TIME_WAIT状态,在此调用时,会出现端口占用的错误。所用要用端口复用

端口复用最常用的用途是:
防止服务器重启时之前绑定的端口还未释放
程序突然退出而系统没有释放端口

#include 
#include 
// 设置套接字的属性(不仅仅能设置端口复用)
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_toptlen);
参数:
	- sockfd : 要操作的文件描述符
	- level : 级别 - SOL_SOCKET (端口复用的级别)
	- optname : 选项的名称
		- SO_REUSEADDR
		- SO_REUSEPORT
	- optval : 端口复用的值(整形)
		- 1 : 可以复用
		- 0 : 不可以复用
	- optlen : optval参数的大小
端口复用,设置的时机是在服务器绑定端口之前。
setsockopt();
bind();

你可能感兴趣的:(面试题,linux,c++,tcp/ip,网络协议,网络)