欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ Thread實現(xiàn)簡單的socket多線程通信

 更新時間:2022年07月05日 11:28:57   作者:合工大機器人實驗室  
本文主要介紹了C++ Thread實現(xiàn)簡單的socket多線程通信,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

起因

為什么要用C++的Thread,很簡單,因為我菜

一打五用pthread實現(xiàn)了socket多線程通信,我之前學并發(fā)的時候沒看pthread,因此代碼只能看個大概,后面還是要系統(tǒng)學一下pthread的

服務端

多線程功能放在騰訊云服務器上,代碼如下:

#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 << "接收客戶端數(shù)據(jù)失敗!" << endl;
? ? ? ? ? ? tcplck.unlock();
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? cout << "服務端接收數(shù)據(jù):" << buffer << endl;

? ? ? ? strcpy(buffer, "I am your father!");
? ? ? ? if (!server.tcpSend(clientfd, buffer, sizeof(buffer)))
? ? ? ? {
? ? ? ? ? ? cout << "向客戶端發(fā)送數(shù)據(jù)失敗!" << endl;
? ? ? ? ? ? tcplck.unlock();
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? tcplck.unlock();
?? ??? ??? ??? ?usleep(100);
? ? }
? ? cout << "通信異常!" << endl;
? ? return;
}

實在是很簡單,貽笑大方了

有幾個注意點:

  • 全局變量在main函數(shù)執(zhí)行完后會銷毀,線程中用到了全局變量server,線程detach后要保證數(shù)據(jù)的收發(fā),就要保持server的生存期,這里體現(xiàn)為在main中循環(huán)等待客戶端的連接
  • 要用鎖鎖住線程中server的操作,避免不同線程同時操作server造成混亂
  • usleep(100);是為了避免不同線程爭搶同一把鎖而造成死鎖的發(fā)生

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 << "向服務端發(fā)送報文失??!" << 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();
}

很簡單,訂閱了手柄發(fā)布的話題/cmd_vel,在回調函數(shù)中和服務端通訊

話題的發(fā)布頻率是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 << "向服務端發(fā)送報文失敗!" << 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!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):I am king of the world!
Tcp thread 140662354179840 is joinable!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):Ouch!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):Ouch!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):Ouch!
服務端接收數(shù)據(jù):I am king of the world!
服務端接收數(shù)據(jù):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實現(xiàn)簡單的socket多線程通信的文章就介紹到這了,更多相關C++  socket多線程通信內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 深入理解C語言的邏輯控制

    深入理解C語言的邏輯控制

    這篇文章主要介紹了C語言的邏輯控制,對C語言的邏輯控制有較為深入的剖析,需要的朋友可以參考下
    2014-07-07
  • Qt實現(xiàn)電子時鐘

    Qt實現(xiàn)電子時鐘

    這篇文章主要為大家詳細介紹了Qt實現(xiàn)電子時鐘,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++Primer筆記之順序容器的使用詳解

    C++Primer筆記之順序容器的使用詳解

    本篇文章對C++Primer 順序容器的使用進行了詳細的分析介紹。需要的朋友參考下
    2013-05-05
  • C++迷宮問題的求解算法

    C++迷宮問題的求解算法

    這篇文章主要為大家詳細介紹了C++迷宮問題的求解算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++ 封裝 DLL 供 C# 調用詳細介紹

    C++ 封裝 DLL 供 C# 調用詳細介紹

    這篇文章主要介紹了C++ 封裝 DLL 供 C# 調用(以C# 調用C++ 二次封裝的VLC播放庫為介質,支持回調函數(shù)的封裝),需要的朋友可以參考下面我文章的具體內容
    2021-09-09
  • C語言文件操作 fopen, fclose, mkdir詳解

    C語言文件操作 fopen, fclose, mkdir詳解

    本文給大家詳細介紹了下C語言的文件操作函數(shù)fopen, fclose, mkdir的用法及示例,非常的簡單實用,有需要的小伙伴可以參考下。
    2016-03-03
  • 引用numpy出錯詳解及解決方法

    引用numpy出錯詳解及解決方法

    這篇文章主要介紹了引用numpy出錯 解決方法的相關資料,需要的朋友可以參考下
    2017-02-02
  • C++對cin輸入字符的判斷及分段函數(shù)處理方法示例

    C++對cin輸入字符的判斷及分段函數(shù)處理方法示例

    這篇文章主要介紹了C++對cin輸入字符的判斷及分段函數(shù)處理方法,結合實例形式分析了C++輸入判斷及處理相關操作技巧,需要的朋友可以參考下
    2017-09-09
  • C++中二進制數(shù)據(jù)序列化和反序列化詳解

    C++中二進制數(shù)據(jù)序列化和反序列化詳解

    這篇文章主要為大家詳細介紹了C++中二進制數(shù)據(jù)序列化和反序列化的相關知識,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下
    2023-11-11
  • C語言實現(xiàn)簡單掃雷小游戲

    C語言實現(xiàn)簡單掃雷小游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單掃雷小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10

最新評論