自定义协议:如何实现keepalive
创始人
2024-05-27 05:54:19
0

高可用协议招式:keepalive

  • 什么是keepalive
  • tcp如何实现keepalive
  • http如何实现keepalive
  • 自定义协议时该怎样实现keepalive

什么是keepalive

Keepalive是一种技术,它可以帮助保持网络连接活跃,避免链路失效。它可以通过给双方发送定期的探测报文,来确认对侧主机是否仍然处于可用状态,并采取必要的措施保持链路的连接性、可靠性和可用性。

tcp如何实现keepalive

tcp提供了相关函数

客户端TCP keep-alive:
// 设置keep-alive参数
int optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(int));
// 设置keep-alive间隔 
optval = 10; // 10s 
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(int));
// 设置探测次数 
optval = 3; // 每10s探测3次 
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(int));
// 设置探测间距 
optval = 2; // 每2s探测一次 
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(int));

http如何实现keepalive

http在1.1版本实现了keepalive
HTTP/1.1实现keep-alive的方法如下:

  1. 客户端向服务端发出请求时附带Connection: keep-alive
request = "GET / HTTP/1.1\r\n" + \ 
"Host: example.com\r\n" + \
"Connection: keep-alive\r\n" + \ # 附带此行
"\r\n"
  1. 服务端正常回复,并附带上Connection: keep-alive
response = "HTTP/1.1 200 OK\r\n" + \ 
"Connection: keep-alive\r\n" + \ # 附带此行
"Content-Length: {}\r\n".format(len(data)) + \
"\r\n" + data
  1. 客户端重用连接,后续请求仍使用此TCP连接
request = "GET /other_url HTTP/1.1\r\n" + \ 
"Host: example.com\r\n" + \
"Connection: keep-alive\r\n" + \ # 仍然附带此行
"\r\n"

自定义协议时该怎样实现keepalive

1.客户端定时发送心跳包:客户端定时发送心跳包,服务端收到后即回复确认码,客户端收到确认码即表示连接状态正常;
2.服务端检测客户端:服务端定时检测客户端是否响应心跳包,若客户端在指定时间内未收到确认码,则关闭该连接;
C++ demo代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define SER_PORT 9999
#define MAX_LEN 1024
#define CLIENT_NUM 10
int main() {int sockfd, client_fd[CLIENT_NUM] = {0}; // 套接字描述符struct sockaddr_in server_addr, client_addr; // 地址信息socklen_t addrlen = sizeof(sockaddr); // 地址信息长度char buf[MAX_LEN]; // 数据缓冲区int opt = 1; // 优化选项// 定义epoll句柄int epfd;struct epoll_event ev, events[CLIENT_NUM];memset(&ev, 0, sizeof(ev));// 初始化服务器地址bzero(&server_addr, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SER_PORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);// 创建套接字if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {cout << "Create Socket failed!" << endl;return -1;}// 设置优化选项setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));// 绑定地址if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) {cout << "Bind Failed!" << endl;return -1;}// 监听if (listen(sockfd, 5) < 0) {cout << "Listen Failed!" << endl;return -1;}// 创建epollepfd = epoll_create(CLIENT_NUM);ev.events = EPOLLIN;ev.data.fd = sockfd;epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);// 循环处理客户端请求while(1){int retval;retval = epoll_wait(epfd, events, CLIENT_NUM, -1); // -1表示永远等待// 遍历retval个就绪事件for (int i = 0; i < retval; ++i){// 客户端连接请求if (events[i].data.fd == sockfd && events[i].events & EPOLLIN){// 接收客户端连接int conn_fd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);if (conn_fd < 0){cout << "Accept Failed!" << endl;return -1;}// 设置新的监听事件ev.events = EPOLLIN;ev.data.fd = conn_fd;epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);// 设置客户端socket为非阻塞int flag = fcntl(conn_fd, F_GETFL);flag |= O_NONBLOCK;fcntl(conn_fd, F_SETFL, flag);cout << "A New Client Connection: " << inet_ntoa(client_addr.sin_addr) << endl;}// 客户端消息if (events[i].data.fd > 0 && events[i].events & EPOLLIN){// 遍历已连接描述符for (int j = 0; j < CLIENT_NUM; ++j){// 接收客户端消息if (events[i].data.fd == client_fd[j]){int len = recv(client_fd[j], buf, MAX_LEN, 0);if (len > 0){// 获取消息类型int type = (unsigned int)buf;switch (type){// 处理心跳包case 0x10:// 向客户端发送确认码send(events[i].data.fd, "\x12\x00\x00\x00", 4, 0);break;// 处理客户端数据case 0x11:// 处理客户端发来的数据cout << "Client Data: " << buf << endl;break;default:break;}}}}}}}close(sockfd);return 0;
}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...