学习笔记c++(socket⽹络编程,⼼跳监测,断线重连,结构
体发送接收)
server.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 *send_thread, *recv_thread, *heartbeat_thread;
int socket_fd, client_fd;
string server_ip;
unsigned short server_port;
bool isServerwork;
bool heart_flag;
uint64_t heartbeat_time;
char recv_buf[BUF_SIZE];
char send_buf[BUF_SIZE];
char key_input_buf[BUF_SIZE];
bool init_server(string ip, unsigned short port);
void start();
void on_connected();
void on_disconnected();
public:
Server();
void send_msg(char *buf);
void recv_msg();
void send_thread_function();
void recv_thread_function();
void recv_thread_function();
void heartbeat_send_thread_function(); //发送⼼跳
void send_server_msg(); //制作并发送结构体信息
void handle_msg(Msg &msg); //处理打印结构体信息
void handle_heartbeat(); //处理⼼跳
};
server.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 "server.h"
Server::Server()
{
socket_fd = -1;
server_ip = "127.0.0.1";
server_port = 8888;
heart_flag = false;
isServerwork = true;
init_server(server_ip,server_port);
}
bool Server::init_server(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 reuseaddr = 1;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
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()
{
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)
{
send_thread = new thread(bind(&Server::send_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::send_msg(char *buf)
{
memset(send_buf,0,BUF_SIZE);
memcpy(send_buf, buf, sizeof(buf));
send(client_fd, send_buf, strlen(send_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_sec * 1000 + recv_now.tv_usec / 1000;
}
else  //处理结构体信息
{
Msg msg;
t, 0 ,t));
memcpy(&msg, recv_buf, sizeof(msg));
handle_msg(msg);
}
}
void Server::on_disconnected()
{
//send_thread->join();
//recv_thread->join();
//delete send_thread;
//delete recv_thread;
//send_thread = nullptr;
//recv_thread = nullptr;
close(socket_fd);
close(client_fd);
}
void Server::send_thread_function()
{
while (true)
{
memset(key_input_buf,0,BUF_SIZE);
fgets(key_input_buf,BUF_SIZE, stdin);
if(strncasecmp(key_input_buf, EXIT, strlen(EXIT)) == 0 )
{
cout<<"exit"<<endl;
isServerwork = false;
break;
}
//send_msg(key_input_buf);//发送⼿动输⼊信息
send_server_msg();//发送结构体信息
}
}
void Server::recv_thread_function()
connect和join的区别{
while (true)
{
recv_msg();
}
}
void Server::heartbeat_send_thread_function()
{
while (isServerwork)
{
unsigned char sendbuf[8] = {0};
sendbuf[0] = 'h';
sendbuf[1] = 'e';
sendbuf[2] = 'a';
sendbuf[3] = 'r';
sendbuf[4] = 't';
send(client_fd, sendbuf, sizeof(sendbuf), 0);
sleep(2);
}
}
void Server::send_server_msg()  //制作并发送结构体信息
{
Msg msg;
t, 0 ,t));
msg.fromID = 22;
char send_content[] = "hello this is server send message info";    t, send_content, sizeof(send_content));
send(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_sec * 1000 + now.tv_usec/1000; //每次获取当前时间
if( (now_time - heartbeat_time) > 1000)
{
//cout<<"heartbeat_timeout_cnt++"<<endl;
heartbeat_timeout_cnt++;
}else
{
heartbeat_timeout_cnt = 0;
}
if(heartbeat_timeout_cnt > 5)  //判断5次⼼跳超时,退出⼼跳检测,关闭client_fd等等重新连接        {
cout<<"heartbeat timeout"<<endl;
heart_flag = false;
heartbeat_timeout_cnt = 0;
//cout<<"client_fd:"<<client_fd<<endl;
if (client_fd > 0) {
shutdown(client_fd, SHUT_RDWR);
close(client_fd);
client_fd = -1;
cout<<"close connection, and reconnect"<<endl;
}
break;
}
}
}
server_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 "server.h"
int main()
{
Server server;
return 0;
}
client.h

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。