面试题答案
一键面试TCP协议三次握手建立连接过程
- 第一次握手:客户端向服务器发送一个SYN(同步序列号)包,该包中包含客户端选择的初始序列号(seq=x)。客户端进入SYN_SENT状态,等待服务器确认。
- 第二次握手:服务器接收到客户端的SYN包后,向客户端发送一个SYN + ACK包。其中,SYN部分的序列号为服务器选择的初始序列号(seq=y),ACK部分是对客户端SYN包的确认,确认号为客户端的序列号加1(ack=x+1)。服务器进入SYN_RCVD状态。
- 第三次握手:客户端接收到服务器的SYN + ACK包后,向服务器发送一个ACK包。该ACK包的确认号为服务器的序列号加1(ack=y+1),序列号为客户端第一次发送的序列号加1(seq=x+1)。此时,客户端和服务器都进入ESTABLISHED状态,连接建立成功。
C语言网络编程中实现函数
- 第一次握手(客户端):
- 使用
socket
函数创建套接字。例如:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- 使用
connect
函数发起连接,此函数会触发第一次握手的SYN包发送。
struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr); connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
- 使用
- 第二次握手(服务器):
- 同样先使用
socket
函数创建套接字。
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
- 使用
bind
函数将套接字绑定到特定的地址和端口。
struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERVER_PORT); servaddr.sin_addr.s_addr = INADDR_ANY; bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
- 使用
listen
函数使套接字进入监听状态,准备接收客户端连接。
listen(listenfd, BACKLOG);
- 使用
accept
函数接受客户端连接,此函数会处理第二次握手的SYN + ACK包的发送以及第三次握手ACK包的接收。
int connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
- 同样先使用
- 第三次握手(客户端):由
connect
函数完成第三次握手的ACK包发送,客户端无需额外调用函数。当服务器accept
函数返回时,表明第三次握手完成,连接建立成功。