学习笔记c++(socket⽹络编程,⼼跳监测,断线重连,结构
体发送接收)
rver.h
/*
* @Author: Li Chao
* @Date: 2020-11-03 08:38:56
* @Last Modified by: Li Chao
* @Last Modified time: 2020-11-03 17:03:45
*/
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <thread>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
using namespace std;
#define BUF_SIZE 0xFFFF
#define EXIT "EXIT"
struct Msg
{
int type;
int fromID;
int toID;
char content[1024];
};
class Server
{
private:
thread *nd_thread, *recv_thread, *heartbeat_thread;
int socket_fd, client_fd;
string rver_ip;
unsigned short rver_port;
bool isServerwork;
bool heart_flag;
uint64_t heartbeat_time;
char recv_buf[BUF_SIZE];
char nd_buf[BUF_SIZE];
小学三年级英语mp3char key_input_buf[BUF_SIZE];
bool init_rver(string ip, unsigned short port);
void start();
void on_connected();
void on_disconnected();
public:
Server();
void nd_msg(char *buf);
void recv_msg();
void nd_thread_function();
void recv_thread_function();
食甚是什么意思void recv_thread_function();
void heartbeat_nd_thread_function(); //发送⼼跳
void nd_rver_msg(); //制作并发送结构体信息
void handle_msg(Msg &msg); //处理打印结构体信息
void handle_heartbeat(); //处理⼼跳
};
rver.cpp
/*
* @Author: Li Chao
* @Date: 2020-11-03 10:50:47
* @Last Modified by: Li Chao
* @Last Modified time: 2020-11-03 17:43:41
*/
#include "rver.h"
Server::Server()
{
socket_fd = -1;
rver_ip = "127.0.0.1";
rver_port = 8888;
heart_flag = fal;
isServerwork = true;
init_rver(rver_ip,rver_port);
}
bool Server::init_rver(string ip, unsigned short port)
{
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd == -1)
{
perror("socket");
exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
int reuaddr = 1;
tsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuaddr, sizeof(reuaddr));
int ret = bind(socket_fd, (struct sockaddr*)&addr, sizeof(addr));
if(ret == -1)
{
perror("bind");
exit(-1);
}
listen(socket_fd, 30);
cout<<"wait client connect"<<endl;
阅兵 英文
start();
return true;
}
void Server::start()
{freeform
struct sockaddr_in client;
socklen_t len = sizeof(client);
while (isServerwork) //不输⼊exit退出,就⼀直循环等等客户端接⼊
{
client_fd = accept(socket_fd, (struct sockaddr*)&client, &len);
if(client_fd == -1)
{
perror("accept");
exit(-1);
}
char *client_ip = inet_ntoa(client.sin_addr);
cout<<"client ip:"<<client_ip<<"connect ok!"<<endl;
if(!heart_flag)
{
nd_thread = new thread(bind(&Server::nd_thread_function, this)); recv_thread = new thread(bind(&Server::recv_thread_function, this)); heartbeat_thread = new thread(bind(&Server::handle_heartbeat, this)); heart_flag = true;
}
}
on_disconnected();
}
void Server::nd_msg(char *buf)
{
memt(nd_buf,0,BUF_SIZE);
memcpy(nd_buf, buf, sizeof(buf));
nd(client_fd, nd_buf, strlen(nd_buf), 0);
}
void Server::recv_msg()
{
int recv_size = recv(client_fd, recv_buf, sizeof(recv_buf), 0);
if(recv_size <= 0)
{
return;
}
if(recv_size == 8)//进⼊⼼跳打印
{
cout<<"recv_size:"<<recv_size<<endl;
cout<<"recv content:"<<recv_buf<<endl;
struct timeval recv_now;
gettimeofday(&recv_now, NULL);
heartbeat_time = recv_now.tv_c * 1000 + recv_now.tv_uc / 1000;
}
el //处理结构体信息
{
Msg msg;
t, 0 ,t));
memcpy(&msg, recv_buf, sizeof(msg));
handle_msg(msg);
1 65用英语怎么读}
}
void Server::on_disconnected()
{
//nd_thread->join();
//recv_thread->join();
//delete nd_thread;
//delete recv_thread;
//nd_thread = nullptr;
my favorite job//recv_thread = nullptr;nta
clo(socket_fd);
clo(client_fd);
}
void Server::nd_thread_function()
{
while (true)
{
memt(key_input_buf,0,BUF_SIZE);
fgets(key_input_buf,BUF_SIZE, stdin);
if(strncacmp(key_input_buf, EXIT, strlen(EXIT)) == 0 )
{
cout<<"exit"<<endl;
isServerwork = fal;
break;
}
//nd_msg(key_input_buf);//发送⼿动输⼊信息
nd_rver_msg();//发送结构体信息
}
}
void Server::recv_thread_function()
你问我答
{
while (true)
{
recv_msg();
}
}
void Server::heartbeat_nd_thread_function()
{
while (isServerwork)
{
unsigned char ndbuf[8] = {0};
ndbuf[0] = 'h';
ndbuf[1] = 'e';
ndbuf[2] = 'a';
ndbuf[3] = 'r';
ndbuf[4] = 't';
nd(client_fd, ndbuf, sizeof(ndbuf), 0);
sleep(2);
}
}
void Server::nd_rver_msg() //制作并发送结构体信息
{
Msg msg;
t, 0 ,t));
msg.fromID = 22;
char nd_content[] = "hello this is rver nd message info"; t, nd_content, sizeof(nd_content));
nd(client_fd, (char *)&msg, sizeof(msg), 0);
}
void Server::handle_msg(Msg &msg) //处理打印结构体信息
{
cout<<"pe:"<&pe<<endl;
cout<<"msg.fromID:"<<msg.fromID<<endl;
cout<<"ID:"<&ID<<endl;
cout<<"t:"<&t<<endl;
}
void Server::handle_heartbeat() //监听⼼跳
{
struct timeval now;
static int heartbeat_timeout_cnt = 0;
while (heart_flag)
{
usleep(500 * 1000);
gettimeofday(&now, NULL);
uint64_t now_time = now.tv_c * 1000 + now.tv_uc/1000; //每次获取当前时间
if( (now_time - heartbeat_time) > 1000)
{
//cout<<"heartbeat_timeout_cnt++"<<endl;
heartbeat_timeout_cnt++;
}el
{
ankle什么意思heartbeat_timeout_cnt = 0;
}
if(heartbeat_timeout_cnt > 5) //判断5次⼼跳超时,退出⼼跳检测,关闭client_fd等等重新连接 {留学中介排行榜
cout<<"heartbeat timeout"<<endl;
heart_flag = fal;
heartbeat_timeout_cnt = 0;
//cout<<"client_fd:"<<client_fd<<endl;
if (client_fd > 0) {
shutdown(client_fd, SHUT_RDWR);
clo(client_fd);
client_fd = -1;
cout<<"clo connection, and reconnect"<<endl;
}
break;
}
}
}
rver_main.cpp
/*
* @Author: Li Chao
* @Date: 2020-11-03 14:44:12
* @Last Modified by: Li Chao
* @Last Modified time: 2020-11-03 14:49:42
*/
#include "rver.h"
int main()
{
Server rver;
return 0;
}
client.h