C++實現(xiàn)本地TCP通訊的示例代碼
更新時間:2024年02月23日 08:32:39 作者:點PY
這篇文章主要為大家詳細介紹了C++如何利用TCP技術(shù),實現(xiàn)本地ROS1和ROS2的通訊,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
概要
利用TCP技術(shù),實現(xiàn)本地ROS1和ROS2的通訊。
服務(wù)端代碼
頭文件
#include <ros/ros.h> #include "std_msgs/String.h" #include "std_msgs/Bool.h" #include <iostream> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include "geometry_msgs/Twist.h" using namespace std; class TCPPublisher { public: TCPPublisher(); ~TCPPublisher(); void cmdVelCallback(const geometry_msgs::Twist::ConstPtr& msg); private: ros::NodeHandle n, nPrivate; ros::Publisher tcpPub; ros::Subscriber cmdVelSub; // 創(chuàng)建服務(wù)器套接字 int serverSocket; // 設(shè)置服務(wù)器地址結(jié)構(gòu) sockaddr_in serverAddr; int clientSocket; std::string topicStatus; };
源代碼
#include "./tcp_pub/tcp_pub.h" TCPPublisher::TCPPublisher():nPrivate("~") { nPrivate.param("topicStatus", topicStatus, std::string("/cmd_vel")); /*訂閱話題*/ cmdVelSub = n.subscribe(topicStatus.c_str(), 10, &TCPPublisher::cmdVelCallback, this); serverSocket = socket(AF_INET, SOCK_STREAM, 0); // 設(shè)置服務(wù)器地址結(jié)構(gòu) sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(8080); // 服務(wù)器監(jiān)聽的端口號 // 綁定套接字 if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { std::cerr << "Bind failed." << std::endl; close(serverSocket); return; } // 監(jiān)聽連接 if (listen(serverSocket, SOMAXCONN) == -1) { std::cerr << "Listen failed." << std::endl; close(serverSocket); return; } std::cout << "Server is listening for incoming connections..." << std::endl; ROS_INFO("TCPPublisher init successfully!!!"); } TCPPublisher::~TCPPublisher() { close(serverSocket); } void TCPPublisher::cmdVelCallback(const geometry_msgs::Twist::ConstPtr& msg) { float velX = msg->linear.x; float angularZ = msg->angular.z; // ROS_INFO("velX : %f, angularZ : %f", velX, angularZ); // 定義字符數(shù)組,用于存儲轉(zhuǎn)換后的結(jié)果 char buffer[50]; // 適當(dāng)調(diào)整數(shù)組大小以適應(yīng)你的需求 snprintf(buffer, sizeof(buffer), "%f,%f", velX, angularZ); // ROS_INFO("buffer %s", buffer); // 接受連接 int clientSocket = accept(serverSocket, NULL, NULL); if (clientSocket == -1) { std::cerr << "Accept failed." << std::endl; close(serverSocket); return; } std::cout << "Connection established with a client." << std::endl; // 發(fā)送消息給客戶端 const char* message = buffer; ROS_INFO("message %s", message); if (send(clientSocket, message, strlen(message), 0) == -1) { std::cerr << "Error sending message." << std::endl; } // 關(guān)閉客戶端套接字 close(clientSocket); } int main(int argc, char **argv) { //創(chuàng)建節(jié)點 ros::init(argc, argv, "pure_pursuit"); TCPPublisher tp; ros::spin(); return 0; }
客戶端代碼
#include <rclcpp/rclcpp.hpp> #include <geometry_msgs/msg/twist.hpp> #include <iostream> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> int main(int argc, char * argv[]) { rclcpp::init(argc, argv); auto node = std::make_shared<rclcpp::Node>("tcp_client"); /*define publisher*/ rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr cmd_pub_; // Advertise velocity commands auto default_qos = rclcpp::QoS(rclcpp::SystemDefaultsQoS()); cmd_pub_ = node->create_publisher<geometry_msgs::msg::Twist>("cmd_vel", default_qos); //連接到服務(wù)器 // if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { // std::cerr << "Connection failed." << std::endl; // close(clientSocket); // return 1; // } // std::cout << "Connected to the server." << std::endl; while (true) { // 創(chuàng)建客戶端套接字 int clientSocket = socket(AF_INET, SOCK_STREAM, 0); if (clientSocket == -1) { std::cerr << "Failed to create client socket." << std::endl; return 1; } // 設(shè)置服務(wù)器地址結(jié)構(gòu) sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // 本地回環(huán)地址 // 服務(wù)器的 IP 地址 serverAddr.sin_port = htons(8080); // 服務(wù)器監(jiān)聽的端口號 // 連接到服務(wù)器 if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { std::cerr << "Connection failed." << std::endl; close(clientSocket); // return 1; } // std::cout << "Connected to the server." << std::endl; // 接收消息 char buffer[50]; memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, sizeof(buffer), 0) == -1) { std::cerr << "Error receiving message." << std::endl; } else { std::cout << "Received message from server: " << buffer << std::endl; // 定義兩個變量來存儲解析后的浮點數(shù) float floatValue1, floatValue2; // 使用 sscanf 解析字符數(shù)組 if (std::sscanf(buffer, "%f,%f", &floatValue1, &floatValue2) == 2) { // 打印解析結(jié)果 std::cout << "解析后的浮點數(shù)1: " << floatValue1 << std::endl; std::cout << "解析后的浮點數(shù)2: " << floatValue2 << std::endl; } else { // 解析失敗 std::cerr << "解析失敗" << std::endl; } geometry_msgs::msg::Twist cmd_msg; cmd_msg.linear.x = floatValue1; cmd_msg.angular.z = floatValue2; cmd_pub_->publish(cmd_msg); std::cout << "Publishing zero speed to /cmd_vel. " << std::endl; } // 關(guān)閉客戶端套接字 close(clientSocket); // 在這里可以添加一些延時,以避免過于頻繁地連接服務(wù)器 sleep(0.1); } rclcpp::spin(node); rclcpp::shutdown(); return 0; }
到此這篇關(guān)于C++實現(xiàn)本地TCP通訊的示例代碼的文章就介紹到這了,更多相關(guān)C++ TCP通訊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言正則表達式詳解 regcomp() regexec() regfree()用法詳解
C語言處理正則表達式常用的函數(shù)有regcomp()、regexec()、regfree()和regerror(),這里就為大家介紹一下,需要的朋友可以參考一下啊2018-04-04Ubuntu18.04下QT開發(fā)Android無法連接設(shè)備問題解決實現(xiàn)
本文主要介紹了Ubuntu18.04下QT開發(fā)Android無法連接設(shè)備問題解決實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06舉例講解C語言的fork()函數(shù)創(chuàng)建子進程的用法
fork函數(shù)是Linux下一個近乎專有的C語言函數(shù),因為使用時需要調(diào)用unistd.h這個頭文件,這里我們就在Linux環(huán)境下舉例講解C語言的fork()函數(shù)創(chuàng)建子進程的用法,需要的朋友可以參考下2016-06-06