C++ Udp接收组播数据(长连接)
·
1.初始化Socket
bool InitRecvMulticast(SOCKET &iSocktet, QString &iLocalIp, int &iRecvProt, QString &iRecvMulticastIp, QString &iRecvPubMulticastIp)
{
WSADATA wsaData;
if (iSocktet)
{
closesocket(iSocktet)
}
if (!m_IsWSAStartup.load())
{
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return false;
}
else
{
m_IsWSAStartup.store(true);
}
}
iSocktet = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (iSocktet == INVALID_SOCKET)
{
LOG(ERROR) << "recv socket create error: " << WSAGetLastError();
return false;
}
sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(iRecvProt);
my_addr.sin_addr.S_un.S_addr = inet_addr(iLocalIp.toLocal8Bit().data());
if (::bind(iSocktet, (SOCKADDR *)&my_addr, sizeof(my_addr)) == SOCKET_ERROR)
{
LOG(ERROR) << "recv socket bind error: " << WSAGetLastError() << " ip =" << iLocalIp.toLocal8Bit().data();
return false;
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(iRecvMulticastIp.toLocal8Bit().data());
mreq.imr_interface.s_addr = inet_addr(iLocalIp.toLocal8Bit().data()); //指定接口接收组播信息
if (!setsockopt(iSocktet, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)))
{
qDebug() << QString::fromLocal8Bit("加入组播:%1成功").arg(iRecvMulticastIp);
LOG(INFO) << QString::fromLocal8Bit("加入组播:%1成功").arg(iRecvMulticastIp).toLocal8Bit().data();
}
else
{
LOG(ERROR) << QString::fromLocal8Bit("加入组播:%1失败").arg(iRecvMulticastIp).toLocal8Bit().data();
return false;
}
if (m_IsUsedPub == 1 && iRecvMulticastIp != iRecvPubMulticastIp && !iRecvPubMulticastIp.isEmpty())
{
struct ip_mreq pub_mreq;
pub_mreq.imr_multiaddr.s_addr = inet_addr(iRecvPubMulticastIp.toLocal8Bit().data());
pub_mreq.imr_interface.s_addr = inet_addr(iLocalIp.toLocal8Bit().data()); //指定接口接收组播信息
if (!setsockopt(iSocktet, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&pub_mreq, sizeof(pub_mreq)))
{
qDebug() << QString::fromLocal8Bit("加入组播:%1成功").arg(iRecvPubMulticastIp);
LOG(INFO) << QString::fromLocal8Bit("加入组播:%1成功").arg(iRecvPubMulticastIp).toLocal8Bit().data();
}
else
{
LOG(ERROR) << QString::fromLocal8Bit("加入组播:%1失败").arg(iRecvPubMulticastIp).toLocal8Bit().data();
return false;
}
}
//设置接收超时时间
struct timeval overTime;
overTime.tv_sec = 30000;
overTime.tv_usec = 0;
if (setsockopt(iSocktet, SOL_SOCKET, SO_RCVTIMEO, (char *)&overTime, sizeof(overTime)) < 0)
{
printf("socket option SO_RCVTIMEO not support\n");
return false;
}
return true;
}
2.接受udp数据
void recvUdpData(SOCKET &iSocktet, QString &iLocalIp, int &iRecvProt, QString &iRecvMulticastIp, QString &iRecvPubMulticastIp, int iRecvIndex)
{
bool isConnect = false;
if (InitRecvMulticast(iSocktet, iLocalIp, iRecvProt, iRecvMulticastIp, iRecvPubMulticastIp))
{
isConnect = true;
}
while (isConnect)
{
char iRecvBuff[1024] = { '\0' };
SOCKADDR_IN sendAddrIn;
int ret = recvfrom(iSocktet, iRecvBuff, sizeof(iRecvBuff), 0, (sockaddr*)&sendAddrIn, &naddrLen);
if (ret == EWOULDBLOCK || ret == EAGAIN)
{
continue;
}
else if (ret > 0)
{
QByteArray byteArray(recvBuff, recvDataSize);
qDebug() << QStringLiteral("接收到的数据:") << byteArray.toHex();
}
}
std::thread udpSocketThread([&] {
recvUdpData(m_recv_socket_A, m_local_ip_A, m_transport_recv_port_A, m_local_Multicast_ip_A, m_local_Multicast_pub_ip_A, 1);
});
udpSocketThread.detach();
}
3.主函数
std::thread udpSocketThread([&] {
recvUdpData(m_recv_socket_A, m_local_ip_A, m_transport_recv_port_A, m_local_Multicast_ip_A, m_local_Multicast_pub_ip_A, 1);
});
udpSocketThread.detach();
4.头文件
#include <windows.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <QSocketNotifier>
#pragma comment(lib, "ws2_32.lib")
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)