ZLToolKit组播发送接收数据时,win与linux下初始化区别及实例

文章详细描述了ZLToolkit中Socket的初始化过程,包括作为发送方和接收方的不同情况,以及在Windows和Linux环境下对UDP组播的特定设置,如绑定本地IP、设置TTL和组播接口等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ZLToolkit 初始化

只作为发送方

初始化:
Socket::Ptr m_SockRecv;
this->m_SockRecv = Socket::createSocket(nullptr, false);
this->m_SockRecv->bindUdpSock(8003,“192.168.172.11”); //这里特别注意,win下一定要绑定本地IP地址192.168.172.11,不然多个网卡的系统会无法发送数据,linux下可以不绑定本地ip也可以成功发送数据;由于是只作为发送方,可以将绑定端口号设置为组播端口号以外的值,组播端口为8002。

这样就完成了ZLToolkit的初始化操作,下面就可以进行发送数据了。

m_SoundSignalAddr = toolkit::SockUtil::make_sockaddr(“239.0.0.2”, 8002); //这个地址ip为组播地址如:239.0.0.2,port为组播端口号:8002

this->m_SockRecv->send(data.data(),data.size(),(struct sockaddr *) &m_SoundSignalAddr, sizeof(struct sockaddr_in));

只作为接收方

初始化:

Socket::Ptr m_SockRecv;
this->m_SockRecv = Socket::createSocket(nullptr, false);
win32: this->m_SockRecv->bindUdpSock(8002,192.168.172.11); 
linux: this->m_SockRecv->bindUdpSock(8002)//这里特别注意,win下一定要绑定本地IP地址192.168.172.11,不然多个网卡的系统会无法接收数据;linux下相反,一定要不绑定本地ip,不然无法接收数据;由于是只作为接收方,必须将绑定端口号设置为组播端口号,组播端口:8002。

接着进行加入组播设置:

    this->fd = this->m_SockRecv->rawFD();
    SockUtil::setMultiTTL(this->fd); //设置TTL

    SockUtil::setMultiIF(this->fd,192.168.172.11); //设置组播发送网卡

    SockUtil::setMultiLOOP(this->fd,false);//设置不接收本地发送组播数据
    SockUtil::joinMultiAddr(this->fd,239.0.0.2,192.168.172.11);  //加入组播

这样就完成了ZLToolkit的初始化操作,下面就可以正常接收数据了。

既作为接收方又作为发送方

初始化:

Socket::Ptr m_SockRecv;
this->m_SockRecv = Socket::createSocket(nullptr, false);
win32: this->m_SockRecv->bindUdpSock(8002,192.168.172.11); 
linux: this->m_SockRecv->bindUdpSock(8002)//这里特别注意,win下一定要绑定本地IP地址192.168.172.11,不然多个网卡的系统会无法发送/接收数据;linux下相反,一定要不绑定本地ip,不然无法发送/接收数据;由于既接收又发送,必须将绑定端口号设置为组播端口号,组播端口:8002。

接着进行加入组播设置:

    this->fd = this->m_SockRecv->rawFD();
    SockUtil::setMultiTTL(this->fd); //设置TTL

    SockUtil::setMultiIF(this->fd,192.168.172.11); //设置组播发送网卡

    SockUtil::setMultiLOOP(this->fd,false);//设置不接收本地发送组播数据
    SockUtil::joinMultiAddr(this->fd,239.0.0.2,192.168.172.11);  //加入组播

这样就可以发送、接收组播数据了。

完整示例代码只有一个类UdpClient
udpclient.h 如下:

#ifndef _UDPCLIENT_H_
#define _UDPCLIENT_H_

#include <QObject>
#include <qglobal.h>
#include <QLibrary>
#include <QMutex>
#include <QSharedPointer>
#include "Network/Socket.h"

#ifdef WIN32
#include "pcap_windows_include/pcap.h"
#else
#include "pcap_linux_include/pcap.h"
#include <semaphore.h>
#endif

//extern int pcap_data_valid_index;
using namespace toolkit;
typedef std::function<void(const SockException &err)> TErrCallback ;
typedef std::function<void(const Buffer::Ptr& buffer, struct sockaddr* addr, int addr_len)> TRecvDataCallback ;

class UdpClient : public QObject
    {

        Q_OBJECT
    public:
        UdpClient(int bind_port,QString bind_ip,QObject *parent = nullptr);
        UdpClient(QObject *parent = nullptr);
        ~UdpClient();

    protected:
        int m_OwnBindPort; //本地绑定端口
        QString m_OwnBind_Ip; //本地绑定IP
        Socket::Ptr m_SockRecv; //本地sock
        int fd;  //socket fd
        struct sockaddr_storage m_SoundSignalAddr;//声信号处理机sock结构体

        uint64_t m_all_send_lost_number = 0;
        uint64_t m_all_send_number = 0;


    private:
        void makeAddr(struct sockaddr* out, const char* ip, uint16_t port);

        TErrCallback m_ErrCallback;
        TRecvDataCallback m_RecvDataCallback;



    private slots:

        void init();
        void onError(const SockException &err);

        void onRecvData(const Buffer::Ptr& buffer, struct sockaddr* addr, int addr_len);


    public slots:
        bool setIP_and_Port(QString strIP,unsigned short port); //获取IP地址和端口号
        void enableRecv(bool b_recv);//停止/开始接收数据
        void sendData(const QString &ip, int port,  QByteArray);
        void setMulticastParam(QString multicast);
        virtual void initNetData();
        virtual void onRecv(QByteArrayList list);
        virtual void onRecvByte(QString src_ip,int dst_port,QByteArray arr);
        virtual void start();

    signals:
        void toReceiveData(QByteArray buffer);
    };

#endif

udpclient.cpp 如下:

#include "qhelperdata.h"
#include "appconfig.h"
#include "udpclient.h"
#include "Util/util.h"
#include "Util/logger.h"
#include <QDebug>
#include "pcapmodule.h"

UdpClient::UdpClient(int bind_port,QString bind_ip,QObject *parent):QObject(parent)
{
    this->m_OwnBindPort = bind_port;
    this->m_OwnBind_Ip = bind_ip;

        init();

}

UdpClient::UdpClient(QObject *parent):QObject(parent)
{
        init();
}

UdpClient::~UdpClient()
{
        this->m_SockRecv.reset();
}

void UdpClient::enableRecv(bool b_recv)
{
    this->m_SockRecv->enableRecv(b_recv);

}

void UdpClient::makeAddr(struct sockaddr *out, const char* ip, uint16_t port)
{
    struct sockaddr_in &servaddr = *((struct sockaddr_in*)out);
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    servaddr.sin_addr.s_addr = inet_addr(ip);
    bzero(&(servaddr.sin_zero), sizeof servaddr.sin_zero);


}

void UdpClient::sendData(const QString &ip, int port,   QByteArray data)
{

    m_SoundSignalAddr = toolkit::SockUtil::make_sockaddr(ip.toStdString().c_str(), port);

    m_all_send_number++;



    if(-1 ==  this->m_SockRecv->send(data.data(),data.size(),(struct sockaddr *) &m_SoundSignalAddr, sizeof(struct sockaddr_in)))
     {
           m_all_send_lost_number++;

           AppConfig::append(TIPS, QString("----------发送失败总包数:%1----------发送失败率:%2--------").arg(m_all_send_lost_number).arg((m_all_send_lost_number*1.000000/(m_all_send_number)*1000000)));
     }

}

void UdpClient::setMulticastParam(QString multicast)
{
    this->fd = this->m_SockRecv->rawFD();
    SockUtil::setMultiTTL(this->fd);

    SockUtil::setMultiIF(this->fd,this->m_OwnBind_Ip.toStdString().c_str());

    SockUtil::setMultiLOOP(this->fd,false);

    SockUtil::joinMultiAddr(this->fd,multicast.toStdString().c_str(),this->m_OwnBind_Ip.toStdString().c_str());
}

void UdpClient::init()
    {
        QMutexLocker locker(&AppConfig::pcap_mutex);
        this->m_SockRecv = Socket::createSocket(nullptr, false);

    }


void UdpClient::initNetData()
{


            if(true == this->m_SockRecv->bindUdpSock(this->m_OwnBindPort+1/*,this->m_OwnBind_Ip.toStdString()*/))
            {


            }
            else
            {
                QThread::sleep(1);
                AppConfig::append(WRONG, QString("------------------------------this->m_SockRecv->bindUdpSock(this->m_OwnBindPort = 1%,this->m_OwnBind_Ip.toStdString() = 2%) is false.").arg(this->m_OwnBindPort).arg(this->m_OwnBind_Ip));

                return;
            }


        this->m_ErrCallback = std::bind(&UdpClient::onError, this, std::placeholders::_1);
        this->m_SockRecv->setOnErr(this->m_ErrCallback);



    this->m_RecvDataCallback = std::bind(&UdpClient::onRecvData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    this->m_SockRecv->setOnRead(this->m_RecvDataCallback);

}

void UdpClient::onRecv(QByteArrayList list)
    {

    }



void UdpClient::onRecvByte(QString src_ip, int dst_port, QByteArray arr)
{

    }

void UdpClient::start()
    {

    }

void UdpClient::onRecvData(const Buffer::Ptr& data, struct sockaddr* addr, int addr_len)
{
    //qDebug() << "你好"/*QByteArray(data->data(), data->size()).toHex().toUpper()*/ <<endl;
    QByteArray arr =  QByteArray(data->data(), data->size());
    qDebug() << arr <<endl;
    emit toReceiveData(QByteArray(data->data(), data->size()));
}

bool UdpClient::setIP_and_Port(QString strIP,unsigned short port)
{
        this->m_OwnBindPort = port;
        this->m_OwnBind_Ip = strIP;
        return true;
}

void UdpClient::onError(const SockException &err)
{
   AppConfig::append(3, err.what());
}



本实例已经上传到我的资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九江在天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值