socket服务端在客户端高频发送情况下的接收处理

前言

针对客户端发送频率过高而服务端不能及时有效处理的情况。结合自己的实际测试给出以下处理方法。

一、socket服务端的建立

首先对客户端进行绑定(bind)监听(listen):

  // created socket
  int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  struct sockaddr_in serv_addr;
  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;            // ipv4地址
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // 任意地址
  serv_addr.sin_port        = htons(123);       // 端口
  if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) {
    std:cout << "bind failed!!!" << endl;
    // 异常退出
    exit(0);  
  }
  // 进入监听状态,等待客户发起请求
  if (listen(serv_sock, 20) != 0) {
    std::cout << "Listen failed!!!" << endl;
    close(serv_sock);
    // 异常退出
    exit(0);
  }

 二、扫描端口等待客户端连接

由于需要一直监听客户端状态整个扫描过程是while(true)循环过程:

  while (true) {
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    int client_sockfd    = accept(serv_sock, (struct sockaddr*)&client_addr, &client_len);

    thread thread_test = thread([&]() { Dealing(client_sockfd, client_addr); });
    thread_test.detach();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

 当客户端连接后通过Dealing函数与服务端进行数据交互。

三、全部数据获取、存储

void Dealing(const int client_sockfd, const struct sockaddr_in& client_addr) {
  std::cout << "socket client: " << inet_ntoa(client_addr.sin_addr) << " has connnected!!!";
  char socket_message[BYTE_LENGTH];
  std::vector<char> buffer;
  int length = 0;
  int size;

  while (true) {
    memset(socket_message, 0, sizeof(socket_message));
    int rev = recv(client_sockfd, socket_message, sizeof(socket_message), 0);
    if (rev <= 0) {
      std::cout << "socket receve rev = " << rev << endl;
      break;
    }
    std::cout << "socket receve iret = " << rev << endl;

    buffer.insert(buffer.end(), socket_message, socket_message + rev);
    std::cout << "socket data buffer size is: " << buffer.size() << endl;

    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }
  close(client_sockfd);

将接收的数据放入vector容器这个数据缓存区。 

四、容器暂存数据处理

bool CompleteFrame(vector<char>& buffer, int& length) {
  // header length
  if (buffer.size() < HEADERSIZE) {
    return false;
  }
  vector<char>::iterator it = buffer.begin();
  while (buffer.size() >= SIZE) {
    // 帧头检验
    if (*(it) == 0x12) {
      // 根据数据帧提取数据长度
      length = ToInt(buffer[2], buffer[3]);
      return buffer.size() >= (HEADERSIZE + length);
    } else {
      // 对容器头部不为帧头信息的字段逐一进行清除
      it = buffer.erase(it);
    }
  }
  return false;
}

通过容器暂存数据,逐一遍历容器每个数据依据具体的协议信息提取出每一帧的数据,然后即可依据相应协议进行解析处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值