最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?socket通信遇到的問(wèn)題及解決方法

 更新時(shí)間:2023年08月28日 09:04:23   作者:BoBo玩ROS  
這篇文章主要介紹了C++?socket通信遇到的問(wèn)題,通過(guò)代碼修改來(lái)解決這個(gè)問(wèn)題,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下

為了解決這兩個(gè)問(wèn)題,你可以對(duì)代碼進(jìn)行以下修改:

1.處理socket斷開(kāi)的情況:

在recv函數(shù)返回0的判斷分支中,你可以在斷開(kāi)連接時(shí)進(jìn)行一些處理,例如打印提示信息或進(jìn)行重連操作。

if (ret == 0) {
  printf("Remote socket close!!!\n");
  // 處理socket斷開(kāi),例如進(jìn)行重連操作
  Reconnect();
  break;
}

你可以在Reconnect函數(shù)中實(shí)現(xiàn)重新連接的邏輯。

2.處理socket連接沒(méi)有發(fā)送消息的情況:

在接收數(shù)據(jù)失敗的判斷分支中,你可以添加一個(gè)超時(shí)機(jī)制,如果在一定時(shí)間內(nèi)沒(méi)有接收到數(shù)據(jù),就認(rèn)為連接沒(méi)有發(fā)送消息。

if (ret < 0) {
  if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) {
    std::this_thread::sleep_for(std::chrono::microseconds(10));
    continue;
  }
  if (errno == EWOULDBLOCK || errno == EAGAIN) {
    // 沒(méi)有數(shù)據(jù)可讀,可以繼續(xù)執(zhí)行其他任務(wù)
    printf("Failed to receive data!!!\n");
    // 處理連接沒(méi)有發(fā)送消息的情況,例如重新發(fā)送消息或斷開(kāi)連接
    HandleNoMessage();
    continue;
  } else {
    printf("Remote socket error!!!\n");
    break;
  }
}

你可以在HandleNoMessage函數(shù)中實(shí)現(xiàn)處理連接沒(méi)有發(fā)送消息的邏輯。

請(qǐng)注意,以上只是一種修改代碼的思路,具體的實(shí)現(xiàn)方式可能需要根據(jù)你的需求和業(yè)務(wù)邏輯來(lái)進(jìn)行調(diào)整。

要將這段C++代碼改為非阻塞執(zhí)行,需要使用非阻塞的套接字操作和事件循環(huán)機(jī)制。下面是修改后的代碼:

void NtripServer::ThreadHandler(void) {
  int ret;
  char recv_buffer[1024] = {};
  thread_is_running_ = true;
  // 將socket_fd_設(shè)置為非阻塞模式
  if (SetNonBlocking(socket_fd_) == -1) {
    printf("Failed to set socket to non-blocking mode\n");
    return;
  }
  while (thread_is_running_) {
    ret = recv(socket_fd_, recv_buffer, sizeof(recv_buffer), 0);
    if (ret == 0) {
      printf("Remote socket close!!!\n");
      break;
    } else if (ret < 0) {
      if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
        printf("Remote socket error!!!\n");
        break;
      }
    } else {
      // 處理接收到的數(shù)據(jù)
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }
  close(socket_fd_);
  socket_fd_ = -1;
  thread_is_running_ = false;
  service_is_running_ = false;
}

在修改后的代碼中,我們首先調(diào)用SetNonBlocking函數(shù)將socket_fd_設(shè)置為非阻塞模式。然后,在while循環(huán)中,我們使用recv函數(shù)接收數(shù)據(jù),并根據(jù)返回值進(jìn)行處理。

如果recv返回值為0,表示遠(yuǎn)程socket關(guān)閉,我們打印相應(yīng)的信息并跳出循環(huán)。

如果recv返回值小于0,我們首先判斷errno是否為EAGAIN、EWOULDBLOCK或EINTR。如果不是這些錯(cuò)誤碼,表示發(fā)生了其他錯(cuò)誤,我們打印相應(yīng)的信息并跳出循環(huán)。

如果recv返回值大于0,表示成功接收到數(shù)據(jù),我們可以在代碼中添加處理接收到的數(shù)據(jù)的邏輯。

在每次循環(huán)結(jié)束后,我們使用std::this_thread::sleep_for函數(shù)暫停10毫秒,以避免忙等待。

最后,在循環(huán)結(jié)束后,我們關(guān)閉socket_fd_并將其置為-1,同時(shí)將thread_is_running_和service_is_running_標(biāo)志置為false,表示線程已停止。

是的,SetNonBlocking函數(shù)需要自定義。下面是一個(gè)示例的SetNonBlocking函數(shù)的實(shí)現(xiàn):

int SetNonBlocking(int socket_fd) {
  int flags = fcntl(socket_fd, F_GETFL, 0);
  if (flags == -1) {
    return -1;
  }
  if (fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
    return -1;
  }
  return 0;
}

這個(gè)函數(shù)的實(shí)現(xiàn)與之前提到的設(shè)置socket為非阻塞模式的代碼相同。它首先使用fcntl函數(shù)獲取socket_fd的文件描述符標(biāo)志,并將返回值保存在變量flags中。如果獲取失敗,函數(shù)返回-1。

然后,它使用fcntl函數(shù)的F_SETFL命令來(lái)修改socket_fd的文件描述符標(biāo)志。修改的方式是將O_NONBLOCK標(biāo)志添加到原有標(biāo)志中,使用位運(yùn)算符|進(jìn)行操作。如果修改失敗,函數(shù)返回-1。

如果設(shè)置成功,函數(shù)返回0。

下面是修改后的完整代碼示例:

#include <iostream>
#include <thread>
#include <chrono>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
class NtripServer {
public:
  NtripServer() : socket_fd_(-1), thread_is_running_(false), service_is_running_(false) {}
  ~NtripServer() {}
  void Start() {
    if (service_is_running_) {
      std::cout << "Service is already running!" << std::endl;
      return;
    }
    // 創(chuàng)建socket
    socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd_ == -1) {
      std::cout << "Failed to create socket!" << std::endl;
      return;
    }
    // 設(shè)置socket選項(xiàng)
    int optval = 1;
    setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    // 綁定地址和端口
    sockaddr_in server_addr{};
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(1234);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(socket_fd_, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
      std::cout << "Failed to bind address!" << std::endl;
      close(socket_fd_);
      socket_fd_ = -1;
      return;
    }
    // 監(jiān)聽(tīng)連接
    if (listen(socket_fd_, 5) == -1) {
      std::cout << "Failed to listen!" << std::endl;
      close(socket_fd_);
      socket_fd_ = -1;
      return;
    }
    // 啟動(dòng)線程處理連接
    service_is_running_ = true;
    std::thread thread(&NtripServer::ThreadHandler, this);
    thread.detach();
  }
  void Stop() {
    if (!service_is_running_) {
      std::cout << "Service is not running!" << std::endl;
      return;
    }
    service_is_running_ = false;
  }
private:
  int socket_fd_;
  bool thread_is_running_;
  bool service_is_running_;
  void ThreadHandler() {
    int ret;
    char recv_buffer[1024] = {};
    thread_is_running_ = true;
    // 將socket_fd_設(shè)置為非阻塞模式
    if (SetNonBlocking(socket_fd_) == -1) {
      std::cout << "Failed to set socket to non-blocking mode" << std::endl;
      return;
    }
    while (thread_is_running_) {
      ret = recv(socket_fd_, recv_buffer, sizeof(recv_buffer), 0);
      if (ret == 0) {
        std::cout << "Remote socket close!!!" << std::endl;
        break;
      } else if (ret < 0) {
        if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
          std::cout << "Remote socket error!!!" << std::endl;
          break;
        }
      } else {
        // 處理接收到的數(shù)據(jù)
        std::cout << "Received data: " << recv_buffer << std::endl;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    close(socket_fd_);
    socket_fd_ = -1;
    thread_is_running_ = false;
    service_is_running_ = false;
  }
  int SetNonBlocking(int socket_fd) {
    int flags = fcntl(socket_fd, F_GETFL, 0);
    if (flags == -1) {
      return -1;
    }
    if (fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
      return -1;
    }
    return 0;
  }
};
int main() {
  NtripServer server;
  server.Start();
  // 服務(wù)運(yùn)行一段時(shí)間后停止
  std::this_thread::sleep_for(std::chrono::seconds(10));
  server.Stop();
  return 0;
}

在這個(gè)示例代碼中,我們創(chuàng)建了一個(gè)NtripServer類來(lái)管理Ntrip服務(wù)。在Start函數(shù)中,我們創(chuàng)建了一個(gè)socket,并設(shè)置選項(xiàng)、綁定地址和端口,然后開(kāi)始監(jiān)聽(tīng)連接。接著,我們啟動(dòng)一個(gè)線程來(lái)處理連接,線程的入口函數(shù)是ThreadHandler。

在ThreadHandler函數(shù)中,我們將socket_fd_設(shè)置為非阻塞模式,并使用recv函數(shù)接收數(shù)據(jù)。根據(jù)返回值進(jìn)行處理,如果返回值為0,表示遠(yuǎn)程socket關(guān)閉;如果返回值小于0,并且errno不是EAGAIN、EWOULDBLOCK或EINTR,表示發(fā)生了其他錯(cuò)誤;如果返回值大于0,表示成功接收到數(shù)據(jù),我們可以在代碼中添加處理接收到的數(shù)據(jù)的邏輯。

在主函數(shù)中,我們創(chuàng)建了一個(gè)NtripServer對(duì)象,并調(diào)用Start函數(shù)啟動(dòng)服務(wù)。然后,讓服務(wù)運(yùn)行一段時(shí)間后調(diào)用Stop函數(shù)停止服務(wù)。

請(qǐng)注意,這只是一個(gè)簡(jiǎn)單的示例代碼,實(shí)際應(yīng)用中可能需要進(jìn)行更多的錯(cuò)誤處理和邏輯處理。對(duì)于Linux系統(tǒng),可以使用fcntl函數(shù)來(lái)設(shè)置socket為非阻塞模式。在上述代碼中,SetNonBlocking函數(shù)就是用來(lái)設(shè)置socket為非阻塞的。具體來(lái)說(shuō),它通過(guò)調(diào)用fcntl函數(shù),使用F_GETFL命令獲取socket的當(dāng)前標(biāo)志位,然后將O_NONBLOCK標(biāo)志位加入到標(biāo)志位中,再次調(diào)用fcntl函數(shù),使用F_SETFL命令將新的標(biāo)志位設(shè)置回socket。

這樣設(shè)置之后,socket的recv函數(shù)將變?yōu)榉亲枞J剑床粫?huì)一直等待數(shù)據(jù)到達(dá),而是立即返回。如果沒(méi)有數(shù)據(jù)到達(dá),recv函數(shù)將返回-1,并且errno會(huì)被設(shè)置為EAGAIN或EWOULDBLOCK。這樣,我們可以在代碼中根據(jù)返回值和errno來(lái)判斷是否有數(shù)據(jù)到達(dá),并進(jìn)行相應(yīng)的處理。如果在SetNonBlocking函數(shù)中設(shè)置socket為非阻塞模式失敗,可以在調(diào)用該函數(shù)的地方進(jìn)行錯(cuò)誤處理。可以根據(jù)具體情況選擇合適的錯(cuò)誤處理方式,例如打印錯(cuò)誤信息、記錄日志、關(guān)閉socket等。以下是一個(gè)示例的錯(cuò)誤處理代碼:

if (SetNonBlocking(socket_fd) == -1) {
  std::cout << "Failed to set socket to non-blocking mode" << std::endl;
  // 處理錯(cuò)誤,例如關(guān)閉socket
  close(socket_fd);
  return;
}

在上述代碼中,如果SetNonBlocking函數(shù)返回-1,表示設(shè)置socket為非阻塞模式失敗。我們可以打印錯(cuò)誤信息,然后進(jìn)行相應(yīng)的錯(cuò)誤處理,例如關(guān)閉socket。這樣可以確保在設(shè)置失敗的情況下,不會(huì)繼續(xù)使用這個(gè)socket進(jìn)行后續(xù)操作。

相關(guān)文章

  • C++解析特殊符號(hào)tab和換行符號(hào)詳情

    C++解析特殊符號(hào)tab和換行符號(hào)詳情

    這篇文章主要給大家介紹的是C++解析一些特殊符號(hào)tab、換行符號(hào)的一些相關(guān)資料,需要的小伙伴可以參考下面文章的具體內(nèi)容
    2021-09-09
  • C++并查集的原理與使用方法

    C++并查集的原理與使用方法

    并查集是一種樹(shù)型的數(shù)據(jù)結(jié)構(gòu),用于處理不相交集合的合并及查詢問(wèn)題,下面這篇文章主要介紹了C++并查集原理與使用方法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • C語(yǔ)言字符函數(shù)與字符串函數(shù)的實(shí)現(xiàn)示例

    C語(yǔ)言字符函數(shù)與字符串函數(shù)的實(shí)現(xiàn)示例

    C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的<ctype.h>和<string.h>頭文件分別提供了豐富的字符處理和字符串處理函數(shù),本文就來(lái)介紹一下C語(yǔ)言字符函數(shù)與字符串函數(shù)的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2024-11-11
  • 如何將C++源程序改寫(xiě)為C語(yǔ)言

    如何將C++源程序改寫(xiě)為C語(yǔ)言

    C++中主要的與C的區(qū)別最大而且最常用的特性及修改方法,接下來(lái)我們一起來(lái)學(xué)習(xí)他們吧
    2021-08-08
  • C++實(shí)現(xiàn)的鏈表類實(shí)例

    C++實(shí)現(xiàn)的鏈表類實(shí)例

    這篇文章主要介紹了C++實(shí)現(xiàn)的鏈表類,以完整實(shí)例分析了C++實(shí)現(xiàn)鏈表類的定義、插入、刪除、遍歷、統(tǒng)計(jì)等相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • C語(yǔ)言超詳細(xì)講解指向函數(shù)的指針

    C語(yǔ)言超詳細(xì)講解指向函數(shù)的指針

    C語(yǔ)言程序在編譯后,每個(gè)函數(shù)都有一個(gè)首地址(也就是函數(shù)第一條指令的地址),這個(gè)地址稱為函數(shù)的指針??梢远x指向函數(shù)的指針變量,使用指針變量間接調(diào)用函數(shù)
    2022-07-07
  • C++14中binary literals的使用詳解

    C++14中binary literals的使用詳解

    這篇文章主要介紹了C++14中binary literals的使用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • C++開(kāi)發(fā)protobuf動(dòng)態(tài)解析工具

    C++開(kāi)發(fā)protobuf動(dòng)態(tài)解析工具

    這篇文章主要為大家介紹了C++開(kāi)發(fā)protobuf動(dòng)態(tài)解析工具實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • c++ qsort 與sort 對(duì)結(jié)構(gòu)體排序?qū)嵗a

    c++ qsort 與sort 對(duì)結(jié)構(gòu)體排序?qū)嵗a

    這篇文章主要介紹了c++ qsort 與sort 對(duì)結(jié)構(gòu)體排序?qū)嵗a,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-11-11
  • Qt輸入類控件用法超詳細(xì)講解

    Qt輸入類控件用法超詳細(xì)講解

    Qt是一個(gè)著名的GUI框架,用來(lái)開(kāi)發(fā)和用戶交互的圖形界面,作為GUI框架,豐富的控件和靈活的事件機(jī)制是不可或缺的,Qt在這一方面做得非常優(yōu)秀,下面這篇文章主要給大家介紹了關(guān)于Qt輸入類控件用法的相關(guān)資料,需要的朋友可以參考下
    2024-08-08

最新評(píng)論

额敏县| 侯马市| 安丘市| 鄂伦春自治旗| 星子县| 罗平县| 阳高县| 平山县| 福鼎市| 德惠市| 宝坻区| 桐柏县| 芦山县| 高邑县| 讷河市| 京山县| 乐清市| 鄱阳县| 宜宾县| 平顶山市| 余庆县| 黑山县| 尖扎县| 沭阳县| 阿鲁科尔沁旗| 乌拉特后旗| 亳州市| 长岛县| 三明市| 辽源市| 高阳县| 定西市| 融水| 蒙城县| 河西区| 阜康市| 明水县| 衢州市| 镇赉县| 盐边县| 龙泉市|