怎么使用C++ Thread实现简单的socket多线程通信
本篇内容介绍了“怎么使用C++ Thread实现简单的socket多线程通信”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
服务端
多线程功能放在腾讯云服务器上,代码如下:
#include "tcpserver.h"#include <thread>#include <mutex>TcpServer server;mutex tcp_mutex;void tcpFunc(int clientfd);int main(int argc, char *argv[]){ if (server.initServer(6666) == false) { cout << "服务端初始化失败!!!" << endl; return -1; } vector<thread> tcp_vec; while (true) { if (!server.tcpAccept()) { continue; } tcp_vec.emplace_back(tcpFunc, server.m_connectfd); // thread tcpThread(tcpFunc, server.m_connectfd); // if (tcpThread.joinable()) if(tcp_vec.back().joinable()) { // cout << "Tcp thread " << tcpThread.get_id() << "is joinable!" << endl; cout << "Tcp thread " << tcp_vec.back().get_id() << " is joinable!" << endl; tcp_vec.back().detach(); } } return 0;}void tcpFunc(int clientfd){ int buf_len = 0; char buffer[1024]; while (true) { unique_lock<mutex> tcplck(tcp_mutex); memset(buffer, 0, sizeof(buffer)); if (!server.tcpRecv(clientfd, buffer, &buf_len, 5)) { cout << "接收客户端数据失败!" << endl; tcplck.unlock(); break; } cout << "服务端接收数据:" << buffer << endl; strcpy(buffer, "I am your father!"); if (!server.tcpSend(clientfd, buffer, sizeof(buffer))) { cout << "向客户端发送数据失败!" << endl; tcplck.unlock(); break; } tcplck.unlock(); usleep(100); } cout << "通信异常!" << endl; return;}
实在是很简单,贻笑大方了
有几个注意点:
全局变量在main函数执行完后会销毁,线程中用到了全局变量server,线程detach后要保证数据的收发,就要保持server的生存期,这里体现为在main中循环等待客户端的连接
要用锁锁住线程中server的操作,避免不同线程同时操作server造成混乱
usleep(100);是为了避免不同线程争抢同一把锁而造成死锁的发生
ROS客户端
#include "tcpclient.h"#include <ros/ros.h>#include <geometry_msgs/Twist.h>TcpClient client;string send_str = "I am king of the world!";char recv_buff[1024];void client_callback(const geometry_msgs::Twist::ConstPtr &msg){ cout << "vel X:" << msg->linear.x << ";vel Y:" << msg->linear.y << ";angular Z:" << msg->angular.z << endl; if (!client.tcpSend(client.m_sockfd, send_str.data(), send_str.size())) { cout << "向服务端发送报文失败!" << endl; } if (!client.tcpRecv(client.m_sockfd, recv_buff, NULL, 10)) { cout << "从服务端接收报文失败!" << endl; } cout << "接收服务端报文:" << recv_buff << endl << endl;}int main(int argc, char **argv){ ros::init(argc, argv, "joystick_client"); ros::NodeHandle nh; string server_ip = "1.116.137.21"; string loop_ip = "127.0.0.1"; if (client.connectToServer(server_ip.data(), 6666) == false) { cout << "连接失败!!!" << endl; return -1; } ros::Subscriber sub = nh.subscribe("/cmd_vel", 1, client_callback); ros::spin();}
很简单,订阅了手柄发布的话题/cmd_vel,在回调函数中和服务端通讯
话题的发布频率是10Hz,意味着和服务端通讯的频率也是10Hz
普通客户端
#include "tcp/tcpclient.h"int main(int argc, char **argv){ TcpClient client; string server_ip = "1.116.137.21"; string loop_ip = "127.0.0.1"; if (client.connectToServer(server_ip.data(), 6666) == false) { cout << "连接失败!!!" << endl; return -1; } cout << "成功连接服务器!" << endl; char buff[1024]; while (true) { memset(buff, 0, sizeof(buff)); sprintf(buff, "Ouch!"); if (!client.tcpSend(client.m_sockfd, buff, sizeof(buff))) { cout << "向服务端发送报文失败!" << endl; return -1; } memset(buff, 0, sizeof(buff)); if (!client.tcpRecv(client.m_sockfd, buff, NULL, 5)) { cout << "从服务端接收报文失败!" << endl; return -1; } cout << "接收服务端报文:" << buff << endl << endl; sleep(0.1); } return 0;}
这里sleep(0.1);是为了模拟ROS中话题的频率
sleep过长会导致服务端阻塞等待该客户端的消息,从而导致其余客户端与服务端的通信失败(如果客户端中允许的通信延时很短的话)
运行效果
云服务器上的服务端
[root@VM-4-11-centos bin]# ./server_thread
Tcp thread 140662362572544 is joinable!
服务端接收数据:I am king of the world!
服务端接收数据:I am king of the world!
服务端接收数据:I am king of the world!
服务端接收数据:I am king of the world!
Tcp thread 140662354179840 is joinable!
服务端接收数据:I am king of the world!
服务端接收数据:Ouch!
服务端接收数据:I am king of the world!
服务端接收数据:Ouch!
服务端接收数据:I am king of the world!
服务端接收数据:Ouch!
服务端接收数据:I am king of the world!
服务端接收数据:Ouch!
笔记本上的ROS客户端
redwall@redwall-G3-3500:~$ rosrun joystick_client joystick_client
[ERROR] [1656939307.244367879]: [registerPublisher] Failed to contact master at [localhost:11311]. Retrying...
[ INFO] [1656939314.923909682]: Connected to master at [localhost:11311]
vel X:0;vel Y:0;angular Z:0
接收服务端报文:I am your father!vel X:0;vel Y:0;angular Z:0
接收服务端报文:I am your father!vel X:0;vel Y:0;angular Z:0
接收服务端报文:I am your father!
虚拟机的普通客户端
prejudice@prejudice-VirtualBox:~/socket_test/socket_for_linux/bin$ ./tcp_client 成功连接服务器!
接收服务端报文:I am your father!
接收服务端报文:I am your father!
接收服务端报文:I am your father!
“怎么使用C++ Thread实现简单的socket多线程通信”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341