文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++Thread实现简单的socket多线程通信

2024-04-02 19:55

关注

起因

为什么要用C++的Thread,很简单,因为我菜

一打五用pthread实现了socket多线程通信,我之前学并发的时候没看pthread,因此代码只能看个大概,后面还是要系统学一下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 << "接收客户端数据失败!" << 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;
}

实在是很简单,贻笑大方了

有几个注意点:

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!

虚拟机的普通客户端

不足

 到此这篇关于C++ Thread实现简单的socket多线程通信的文章就介绍到这了,更多相关C++  socket多线程通信内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯