c++实如今同一台主机两个步伐实实际时通信

打印 上一主题 下一主题

主题 974|帖子 974|积分 2924

c++代码实现同一台主机两个步伐实实际时通信

对于历程间通信方式有很多种,对于本机两个步伐中可以实时通信那么应该选择哪个呢?很多人最快想到的就是socket通信。
套接字适用于跨网络的历程间通信,具有网络透明性、机动性和安全性高的优点,但性能开销较大,延迟较高!
共享内存适用于同一台呆板上的历程间通信,具有高性能、低延迟和高吞吐量的优点,但需要手动管理同步机制,安全性较低。以是我们优先使用共享内存来实现,在智能驾驶等工业场景中使用非常多。
共享内存实现

历程A:
  1. #include <cstring>
  2. #include <iostream>
  3. #include <sys/shm.h>
  4. #include <thread>
  5. #include <unistd.h>
  6. #define SHM_KEY_A 12345
  7. #define SHM_KEY_B 67890
  8. #define SHM_SIZE 1024
  9. void send_messages(char* send_data)
  10. {
  11.     std::string message;
  12.     while (std::getline(std::cin, message)) {
  13.         if (message == "exit") {
  14.             break;
  15.         }
  16.         strncpy(send_data, message.c_str(), SHM_SIZE - 1);
  17.         send_data[SHM_SIZE - 1] = '\0';
  18.         while (std::strlen(send_data) > 0) {
  19.             usleep(100000); // 等待 100 毫秒
  20.         }
  21.     }
  22. }
  23. void receive_messages(char* recv_data)
  24. {
  25.     while (true) {
  26.         while (std::strlen(recv_data) == 0) {
  27.             usleep(100000); // 等待 100 毫秒
  28.         }
  29.         std::cout << "Received message: " << recv_data << std::endl;
  30.         std::memset(recv_data, 0, SHM_SIZE);
  31.     }
  32. }
  33. int main()
  34. {
  35.     // 创建共享内存A(用于接收消息)
  36.     int shmid_a = shmget(SHM_KEY_A, SHM_SIZE, 0666);
  37.     if (shmid_a == -1) {
  38.         std::cerr << "Failed to get shared memory A" << std::endl;
  39.         return 1;
  40.     }
  41.     // 创建共享内存B(用于发送消息)
  42.     int shmid_b = shmget(SHM_KEY_B, SHM_SIZE, 0666);
  43.     if (shmid_b == -1) {
  44.         std::cerr << "Failed to get shared memory B" << std::endl;
  45.         return 1;
  46.     }
  47.     // 将共享内存连接到当前进程
  48.     char* recv_data = (char*)shmat(shmid_a, nullptr, 0);
  49.     char* send_data = (char*)shmat(shmid_b, nullptr, 0);
  50.     if (recv_data == (char*)-1 || send_data == (char*)-1) {
  51.         std::cerr << "Failed to attach shared memory" << std::endl;
  52.         return 1;
  53.     }
  54.     std::thread sender(send_messages, send_data);
  55.     std::thread receiver(receive_messages, recv_data);
  56.     sender.join();
  57.     receiver.join();
  58.     // 清理共享内存
  59.     shmdt(recv_data);
  60.     shmdt(send_data);
  61.     shmctl(shmid_a, IPC_RMID, nullptr);
  62.     shmctl(shmid_b, IPC_RMID, nullptr);
  63.     return 0;
  64. }
复制代码
历程B:
  1. #include <cstring>
  2. #include <iostream>
  3. #include <sys/shm.h>
  4. #include <thread>
  5. #include <unistd.h>
  6. #define SHM_KEY_A 12345
  7. #define SHM_KEY_B 67890
  8. #define SHM_SIZE 1024
  9. void send_messages(char* send_data)
  10. {
  11.     std::string message;
  12.     while (std::getline(std::cin, message)) {
  13.         if (message == "exit") {
  14.             break;
  15.         }
  16.         strncpy(send_data, message.c_str(), SHM_SIZE - 1);
  17.         send_data[SHM_SIZE - 1] = '\0';
  18.         while (std::strlen(send_data) > 0) {
  19.             usleep(100000); // 等待 100 毫秒
  20.         }
  21.     }
  22. }
  23. void receive_messages(char* recv_data)
  24. {
  25.     while (true) {
  26.         while (std::strlen(recv_data) == 0) {
  27.             usleep(100000); // 等待 100 毫秒
  28.         }
  29.         std::cout << "Received message: " << recv_data << std::endl;
  30.         std::memset(recv_data, 0, SHM_SIZE);
  31.     }
  32. }
  33. int main()
  34. {
  35.     // 获取共享内存A(用于发送消息)
  36.     int shmid_a = shmget(SHM_KEY_A, SHM_SIZE, IPC_CREAT | 0666);
  37.     if (shmid_a == -1) {
  38.         std::cerr << "Failed to create shared memory A" << std::endl;
  39.         return 1;
  40.     }
  41.     // 获取共享内存B(用于接收消息)
  42.     int shmid_b = shmget(SHM_KEY_B, SHM_SIZE, IPC_CREAT | 0666);
  43.     if (shmid_b == -1) {
  44.         std::cerr << "Failed to create shared memory B" << std::endl;
  45.         return 1;
  46.     }
  47.     // 将共享内存连接到当前进程
  48.     char* send_data = (char*)shmat(shmid_a, nullptr, 0);
  49.     char* recv_data = (char*)shmat(shmid_b, nullptr, 0);
  50.     if (send_data == (char*)-1 || recv_data == (char*)-1) {
  51.         std::cerr << "Failed to attach shared memory" << std::endl;
  52.         return 1;
  53.     }
  54.     std::thread sender(send_messages, send_data);
  55.     std::thread receiver(receive_messages, recv_data);
  56.     sender.join();
  57.     receiver.join();
  58.     // 清理共享内存
  59.     shmdt(send_data);
  60.     shmdt(recv_data);
  61.     shmctl(shmid_a, IPC_RMID, nullptr);
  62.     shmctl(shmid_b, IPC_RMID, nullptr);
  63.     return 0;
  64. }
复制代码
代码简洁比较容易。有些捞仔可能会问了,除了共享内存另有没有其它方式呢?有!当然有,只不过性能不如共享内存啦。
命名管道实现

历程A:
  1. #include <fstream>
  2. #include <iostream>
  3. #include <sys/stat.h>
  4. #include <thread>
  5. #include <unistd.h>
  6. #define PIPE_NAME_A "pipe_a"
  7. #define PIPE_NAME_B "pipe_b"
  8. void send_messages(const std::string& pipe_name)
  9. {
  10.     std::ofstream pipe(pipe_name);
  11.     if (!pipe) {
  12.         std::cerr << "Failed to open named pipe for writing" << std::endl;
  13.         return;
  14.     }
  15.     std::cout << "Enter messages to send (type 'exit' to quit):" << std::endl;
  16.     while (true) {
  17.         std::string message;
  18.         std::getline(std::cin, message);
  19.         if (message == "exit") {
  20.             break;
  21.         }
  22.         pipe << message << std::endl;
  23.         pipe.flush();
  24.     }
  25. }
  26. void receive_messages(const std::string& pipe_name)
  27. {
  28.     std::ifstream pipe(pipe_name);
  29.     if (!pipe) {
  30.         std::cerr << "Failed to open named pipe for reading" << std::endl;
  31.         return;
  32.     }
  33.     std::cout << "Waiting for messages..." << std::endl;
  34.     while (true) {
  35.         std::string message;
  36.         std::getline(pipe, message);
  37.         // 处理程序在没有数据时不会频繁地检查管道,从而节省CPU资源,同时保持对新数据的响应
  38.         if (pipe.eof()) {
  39.             sleep(1);
  40.             pipe.clear();
  41.             pipe.seekg(0, std::ios::end);
  42.         } else {
  43.             std::cout << "Received message: " << message << std::endl;
  44.         }
  45.     }
  46. }
  47. int main()
  48. {
  49.     // 创建命名管道
  50.     if (mkfifo(PIPE_NAME_A, 0666) == -1) {
  51.         std::cerr << "Failed to create named pipe A" << std::endl;
  52.         return 1;
  53.     }
  54.     if (mkfifo(PIPE_NAME_B, 0666) == -1) {
  55.         std::cerr << "Failed to create named pipe B" << std::endl;
  56.         return 1;
  57.     }
  58.     std::thread sender(send_messages, PIPE_NAME_A);
  59.     std::thread receiver(receive_messages, PIPE_NAME_B);
  60.     sender.join();
  61.     receiver.join();
  62.     return 0;
  63. }
复制代码
历程B:
  1. #include <fstream>
  2. #include <iostream>
  3. #include <sys/stat.h>
  4. #include <thread>
  5. #include <unistd.h>
  6. #define PIPE_NAME_A "pipe_a"
  7. #define PIPE_NAME_B "pipe_b"
  8. void send_messages(const std::string& pipe_name)
  9. {
  10.     std::ofstream pipe(pipe_name);
  11.     if (!pipe) {
  12.         std::cerr << "Failed to open named pipe for writing" << std::endl;
  13.         return;
  14.     }
  15.     std::cout << "Enter messages to send (type 'exit' to quit):" << std::endl;
  16.     while (true) {
  17.         std::string message;
  18.         std::getline(std::cin, message);
  19.         if (message == "exit") {
  20.             break;
  21.         }
  22.         pipe << message << std::endl;
  23.         pipe.flush();
  24.     }
  25. }
  26. void receive_messages(const std::string& pipe_name)
  27. {
  28.     std::ifstream pipe(pipe_name);
  29.     if (!pipe) {
  30.         std::cerr << "Failed to open named pipe for reading" << std::endl;
  31.         return;
  32.     }
  33.     std::cout << "Waiting for messages..." << std::endl;
  34.     while (true) {
  35.         std::string message;
  36.         std::getline(pipe, message);
  37.         if (pipe.eof()) {
  38.             sleep(1);
  39.             pipe.clear();
  40.             pipe.seekg(0, std::ios::end);
  41.         } else {
  42.             std::cout << "Received message: " << message << std::endl;
  43.         }
  44.     }
  45. }
  46. int main()
  47. {
  48.     std::thread sender(send_messages, PIPE_NAME_B);
  49.     std::thread receiver(receive_messages, PIPE_NAME_A);
  50.     sender.join();
  51.     receiver.join();
  52.     return 0;
  53. }
复制代码
相对于共享内存的优缺点:
优点


  • 简单易用:命名管道的实现相对简单,得当用于简单的历程间通信。
缺点

  • 性能开销:命名管道的性能略低于共享内存,因为数据需要通过内核缓冲区传输。共享内存是所有历程间通信(IPC)机制中最快的,因为它不需要在历程之间复制数据。
  • 单向通信:命名管道通常是单向的,需要两个管道实现双向通信。
还可以使用消息队列实现(本人使用的是wsl2,微软不支持,故没有代码)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81428

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表