短线重连代码实现

客户端

复制代码
//断线重连客户端
#include <arpa/inet.h>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <netinet/in.h>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

using namespace std;

enum class Status {
  NEW,          //要去新建连接了
  CONNECTING,   //重新连接中
  CONNECTED,    //连接成功
  DISCONNECTED, //连接失败,需要重连
  CLOSED        //多次重连失败,关闭连接
};

class ClientConnect {
public:
  ClientConnect(const std::string &ip, int port, int count)
      : count_(count), ip_(ip), port_(port) {}
  ~ClientConnect() { disconnect(); }

  //建立连接
  void connect() {
    fd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (fd_ < 0) {
      std::cout << "socket faild" << std::endl;
      exit(-1);
    }
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port_);
    inet_pton(AF_INET, ip_.c_str(), &addr.sin_addr);
    int ret = ::connect(fd_, (sockaddr *)&addr, sizeof addr);
    if (ret < 0) {
      std::cout << "connect faild" << std::endl;
      disconnect();
      status_ = Status::DISCONNECTED;
      return;
    }
    status_ = Status::CONNECTED;
  }

  //查询当前状态
  Status status() { return status_; }

  //查询socketfd
  int fd() { return fd_; }

  //重连
  void reconnect() {
    status_ = Status::CONNECTING;
    for (int i = 0; i < count_; i++) {
      std::cout << "reconnecting... attempt " << i + 1 << std::endl;
      disconnect();
      connect(); // 调用类成员函数 connect()
      if (status_ == Status::CONNECTED) {
        return;
      }
      sleep(1); // 重连间隔
    }
    status_ = Status::CLOSED;
  }

  void disconnect() {
    if (fd_ != -1) {
      close(fd_);
      fd_ = -1;
    }
    status_ = Status::CLOSED;
  }

  void run() {
    //发送数据
    while (true) {
      std::string s;
      std::cout << "Please input:" << std::endl;
      if (!getline(std::cin, s)) {
        std::cout << "Input finished." << std::endl;
        status_ = Status::CLOSED;
        return;
      }
      if (s.empty()) {
        continue;
      }
      std::cout << "client say:" << s << std::endl;
      int ret = send(fd_, s.c_str(), s.size(), 0);
      if (ret < 0) {
        std::cout << "send error:" << strerror(errno) << std::endl;
        status_ = Status::DISCONNECTED;
        return;
      }
      //接收数据
      char buff[1024];
      int n = recv(fd_, buff, sizeof buff, 0);

      if (n > 0) {
        buff[n] = '\0';
        std::cout << "server say:" << buff << std::endl;
      } else if (n == 0) //连接断开
      {
        status_ = Status::DISCONNECTED;
        return;
      } else {
        std::cout << "error::" << strerror(errno) << endl;
        status_ = Status::CLOSED;
        return;
      }
    }
  }

private:
  Status status_ = Status::NEW;
  int fd_ = -1;
  int count_ = 0; //最大重试次数
  std::string ip_;
  int port_;
};

class TcpClient {
public:
  TcpClient(std::string ip, int port, int count) : cc(ip, port, count) {}
  ~TcpClient() {}
  void start() {
    while (true) {
      switch (cc.status()) {
      case Status::NEW:
        cc.connect();
        break;
      case Status::DISCONNECTED:
        cc.reconnect();
        break;
      case Status::CLOSED:
        cc.disconnect();
        cout << "连接已彻底关闭" << endl;
        return;
      case Status::CONNECTED:
        //发送数据
        cc.run();
        break;
      default:
        break;
      }
    }
  }

private:
  ClientConnect cc;
};

void Usage() { std::cout << "Usage:./client ip port" << std::endl; }

int main(int argc, char *argv[]) {
  if (argc != 3) {
    Usage();
    return 1;
  }
  std::string ip = argv[1];
  int port = std::stoi(argv[2]);
  TcpClient client(ip, port, 6);
  client.start();
}

服务端

复制代码
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <thread>
#include <vector>

void handle_client(int client_fd) {
    char buffer[1024];
    while (true) {
        memset(buffer, 0, sizeof(buffer));
        ssize_t n = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0) {
            std::string received(buffer);
            std::string response = "我收到你的消息:" + received;
            send(client_fd, response.c_str(), response.size(), 0);
            std::cout << "Received: " << received << " | Sent response." << std::endl;
        } else if (n == 0) {
            std::cout << "Client disconnected." << std::endl;
            break;
        } else {
            perror("recv");
            break;
        }
    }
    close(client_fd);
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " <port>" << std::endl;
        return 1;
    }

    int port = std::stoi(argv[1]);
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        return 1;
    }

    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        return 1;
    }

    if (listen(server_fd, 5) < 0) {
        perror("listen");
        return 1;
    }

    std::cout << "Echo Server started on port " << port << std::endl;

    while (true) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd < 0) {
            perror("accept");
            continue;
        }

        std::cout << "New client connected: " << inet_ntoa(client_addr.sin_addr) << std::endl;
        std::thread(handle_client, client_fd).detach();
    }

    close(server_fd);
    return 0;
}

makefile

复制代码
CC = g++
CFLAGS = -Wall -g -pthread -std=c++11

all: server client

server: echo_server.cc
	$(CC) $(CFLAGS) echo_server.cc -o server

client: connect.cc
	$(CC) $(CFLAGS) connect.cc -o client

clean:
	rm -f server client

通过手动结束服务端模拟短线情况

相关推荐
AI视觉网奇2 小时前
audio2face 实时驱动 2026笔记
开发语言·python
陳10302 小时前
C++:list(1)
开发语言·c++
小CC吃豆子2 小时前
如何在 VS Code 中调试 C++ 程序?
开发语言·c++
Overt0p2 小时前
抽奖系统(7)
java·开发语言·spring boot·redis·tomcat·rabbitmq
23zhgjx-hyh2 小时前
【项目四:网络攻击分析】
网络·安全·web安全
JANG10242 小时前
【Qt】项目打包
开发语言·qt
小码吃趴菜2 小时前
http实现服务器与浏览器通信
网络·网络协议·http
muddjsv2 小时前
支撑 TCP/IP 协议运行的核心硬件:从物理层到网络层的全梳理
服务器·网络·tcp/ip
汤愈韬2 小时前
防火墙双机热备01(主备模式)
网络·网络协议·网络安全·security·huawei