C++之TCP三次握手(笔记)

Posted 小懵白生活小趣谈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++之TCP三次握手(笔记)相关的知识,希望对你有一定的参考价值。

C++中TCP三次握手的实现主要还是以socket套接字实现的,也就是客户服务方式。

socket套接字既不是运输层的协议,也不是应用层的协议,而是处于这两者之间的中间软件抽象层,它是一组接口。

1、对于理论知识上讲解:

TCP是面向连接的协议,其运输连接管理主要有三个阶段,即:连接建立、数据传送和连接释放。

建立连接方式如下:

以面试时的口语讲述就是:
第一次握手 : 服务端B被动打开,进行监听端口。而客户端主动打开,向服务端发送连接请求报文段。
此时TCP报头的同步SYN标志位置1,表示希望建立连接,假设TCP报头的序列号为x;
第二次握手: 服务端接收到客户端的请求报文段后,则向客户端发送一个确认报文段。

此时TCP报头的同步SYN、确认ACK标志位置1,表示允许建立连接,此时TCP报头的确认序列号为x+1,假设序列号为y;

第三次握手: 客户端接收到服务端的确认后,还要向服务器发送确认。
此时TCP报头的确认ACK标志位置1,序列号为x+1,确认序列号为y+1;客户端进入 已建立连接 状态。
当服务端收到客户端的确认后,也进入已建立连接状态




理论已经出来了,那么接下来就代码实现了;

对于C++程序编写来说,服务端代码如下:

#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
bool initialization(SOCKET&conn);
int main(){ SOCKET conn; char recvBuf[100]; if(initialization(conn)){ //填写接收客户端发送数据代码 while (1){ recv(conn, recvBuf, 100, 0); }; return 0;} bool initialization(SOCKET&conn) { WSADATA wsaData; SOCKET sockServer; SOCKADDR_IN addrServer; SOCKADDR_IN addr; if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) //初始化套接子库 return false;     sockServer = socket(AF_INET, SOCK_STREAM, 0);  //创建套接字     //准备通信地址 addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrServer.sin_family = AF_INET; addrServer.sin_port = htons(8090);     bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));  //IP、端口绑定  if(listen(sockServer, 5)<0){ //监听端口信息 WSACleanup(); retrun false; } conn = accept(sockServer, (SOCKADDR*)&addr, &len); ////监听客户端连接 return true; }

客户端代码实现如下:

#include <iostream>#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std; bool Init_Client(SOCKET&Client); int main(){   SOCKET Client;  Client= socket(AF_INET, SOCK_STREAM, 0);    if(Init_Client(Client)){    while(1){ cin >> send_buf; send_len = send(Client, send_buf, 100, 0); //............     }  }} bool Init_Client(SOCKET&Client) {
WORD w_req = MAKEWORD(2, 2);//版本号 WSADATA wsadata;
if (WSAStartup(w_req, &wsadata)!= 0) { cout << "初始化套接字库失败!" << endl; return false; } if (connect(Client, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) { cout << "服务器连接失败!" << endl; WSACleanup(); return false;  }  return true;}




也就是说:首先服务器端先初始化Socket对象,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。

客户端通过调用accept函数,向服务端发送一个请求包,将TCP报头的同步SYN标志位置为1,表示希望建立连接,假设序列号为x

服务端接收到客户端的数据包后,发送一个确认包给客户端。

将TCP报文的同步SYN标志位、确认ACK标志位置为1,确认序列号为x+1,表示允许建立连接,假设序列号为y

客户端接收到服务端的相应包后,向服务端发送一个相应包,将TCP报头的确认ACK标志位置为1,确认序列号为y+1.序列号为x+1

如此,两者双方可以进行数据通信了。





对于为什么不能两次握手:

这主要是为了防止已失效的连接请求报文段突然又传送到了服务端B。

此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接。

但此时的客户端会忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,这样就浪费资源。

而所谓的失效的报文段:

是指当客户端发送一个连接请求报文,因久久未能接收到确认,然后重新发生一个连接请求报文。

后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。

但是当第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端。


C++之TCP三次握手(笔记)


END



以上是关于C++之TCP三次握手(笔记)的主要内容,如果未能解决你的问题,请参考以下文章

c++程序员面试题---TCP的“三次握手”和“四次挥手”

学习笔记——TCP“三次握手”和“四次挥手”,简单介绍

Linux运维学习笔记-TCP三次握手和四次挥手

iOS之快速掌握TCP 三次握手、四次分手

计算机网络学习笔记——传输层TCP三次握手四次挥手TCP流量控制大总结

计算机网络学习笔记——传输层TCP三次握手四次挥手TCP流量控制大总结