C++實(shí)現(xiàn)本地TCP通訊的示例代碼
更新時(shí)間:2024年02月23日 08:32:39 作者:點(diǎn)PY
這篇文章主要為大家詳細(xì)介紹了C++如何利用TCP技術(shù),實(shí)現(xiàn)本地ROS1和ROS2的通訊,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
概要
利用TCP技術(shù),實(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)聽的端口號(hào)
// 綁定套接字
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ù)組,用于存儲(chǔ)轉(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é)點(diǎn)
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)聽的端口號(hào)
// 連接到服務(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;
// 定義兩個(gè)變量來存儲(chǔ)解析后的浮點(diǎn)數(shù)
float floatValue1, floatValue2;
// 使用 sscanf 解析字符數(shù)組
if (std::sscanf(buffer, "%f,%f", &floatValue1, &floatValue2) == 2) {
// 打印解析結(jié)果
std::cout << "解析后的浮點(diǎn)數(shù)1: " << floatValue1 << std::endl;
std::cout << "解析后的浮點(diǎn)數(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);
// 在這里可以添加一些延時(shí),以避免過于頻繁地連接服務(wù)器
sleep(0.1);
}
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}到此這篇關(guān)于C++實(shí)現(xiàn)本地TCP通訊的示例代碼的文章就介紹到這了,更多相關(guān)C++ TCP通訊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ vector容器實(shí)現(xiàn)貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C++ vector容器實(shí)現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
C語言正則表達(dá)式詳解 regcomp() regexec() regfree()用法詳解
C語言處理正則表達(dá)式常用的函數(shù)有regcomp()、regexec()、regfree()和regerror(),這里就為大家介紹一下,需要的朋友可以參考一下啊2018-04-04
Ubuntu18.04下QT開發(fā)Android無法連接設(shè)備問題解決實(shí)現(xiàn)
本文主要介紹了Ubuntu18.04下QT開發(fā)Android無法連接設(shè)備問題解決實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
舉例講解C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的用法
fork函數(shù)是Linux下一個(gè)近乎專有的C語言函數(shù),因?yàn)槭褂脮r(shí)需要調(diào)用unistd.h這個(gè)頭文件,這里我們就在Linux環(huán)境下舉例講解C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的用法,需要的朋友可以參考下2016-06-06

