中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么使用C++?Thread實現簡單的socket多線程通信

發布時間:2022-07-06 14:14:59 來源:億速云 閱讀:253 作者:iii 欄目:開發技術

本篇內容介紹了“怎么使用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多線程通信”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

绥阳县| 分宜县| 长垣县| 牟定县| 甘德县| 湘西| 兴文县| 吉安县| 富川| 巴彦县| 西城区| 司法| 仙桃市| 泰顺县| 栾川县| 晴隆县| 离岛区| 蛟河市| 太湖县| 石门县| 石棉县| 洪湖市| 莱西市| 兴国县| 柳林县| 碌曲县| 工布江达县| 和政县| 汶川县| 都匀市| 崇信县| 华安县| 沁源县| 云浮市| 漠河县| 恭城| 佳木斯市| 北京市| 砀山县| 宜宾县| 琼中|