GrabBag/VrNets/UDPClient/Src/CYUDPClient.cpp
2026-07-11 15:49:14 +08:00

175 lines
3.4 KiB
C++

#include "CYUDPClient.h"
CUDPClient::CUDPClient()
: m_sockfd(INVALID_SOCKET)
, m_bRecv(false)
, m_bRecvRuning(false)
, m_funcRecvData(nullptr)
{
}
CUDPClient::~CUDPClient()
{
}
bool IYUDPClient::CreateUDPClient(IYUDPClient** ppIUDPClient)
{
CUDPClient* p = new CUDPClient;
*ppIUDPClient = p;
return true;
}
/**
* 初始化服务
* @brief Init
* @return
*/
int CUDPClient::Init(const bool bBoard)
{
#ifdef _WIN32
//初始化winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif // !_WIN32
m_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (INVALID_SOCKET == m_sockfd)
{
printf("create socket err\n");
return ERR_CODE(NET_ERR_CREAT_INIT);
}
if(bBoard)
{
//设置该套接字为广播类型,
int bOpt = 1;
setsockopt(m_sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));
}
#ifdef _WIN32
unsigned long ul = 1;
ioctlsocket(m_sockfd, FIONBIO, &ul);
#else
int lDisableBlockMode = 1;
ioctl(m_sockfd, FIONBIO, &lDisableBlockMode);
#endif
// 用来从网络上的广播地址接收数据
memset(&m_sin_from, 0, sizeof(m_sin_from));
m_sin_from.sin_family = AF_INET;
m_sin_from.sin_port = htons(0);
m_sin_from.sin_addr.s_addr = INADDR_ANY;
// 绑定套接字
int err = bind(m_sockfd, (sockaddr*)&m_sin_from, sizeof(sockaddr));
if (0 != err)
{
printf("bind socket err\n");
return ERR_CODE(NET_ERR_CREAT_BIND);
}
return SUCCESS;
}
/**
* 开始接收UDP数据
* @brief StartUDPClient
* @return
*/
int CUDPClient::StartUDPClient(UdpClientRecvDataFunc pRecvDataFunc)
{
m_funcRecvData = pRecvDataFunc;
m_bRecv = true;
//启动线程
std::thread recvThread(&CUDPClient::_UdpRecvData, this);
recvThread.detach();
return SUCCESS;
}
/**
* 结束接收UDP数据
* @brief StopUDPClient
* @return
*/
int CUDPClient::StopUDPClient()
{
m_bRecv = false;
_CloseSocket();
while (m_bRecvRuning)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return SUCCESS;
}
/**
* 发送数据
* @brief SendData
* @param pData
* @param nLen
* @return
*/
int CUDPClient::SendData(const int nPort, const char* pAddr, const char* pData, const int nLen)
{
if (INVALID_SOCKET == m_sockfd)
{
return ERR_CODE(NET_ERR_NOTINIT);
}
sockaddr_in sin_to;
memset(&sin_to, 0, sizeof(sin_to));
sin_to.sin_family = AF_INET;
sin_to.sin_port = htons(nPort);
sin_to.sin_addr.s_addr = inet_addr(pAddr);
int nCount = 0;
nCount = sendto(m_sockfd, pData, nLen, 0, (struct sockaddr *)&sin_to, sizeof(sin_to));
if (nCount <= 0)
{
printf("sendto %d udp : %d err : %d\n", m_sockfd, nCount, errno);
}
return ERR_CODE(nCount > 0 ? SUCCESS : NET_ERR_SEND_DATA);
}
void CUDPClient::_CloseSocket()
{
#ifdef _WIN32
closesocket(m_sockfd);
#else
close(m_sockfd);
#endif // _WIN32
m_sockfd = INVALID_SOCKET;
}
void CUDPClient::_UdpRecvData()
{
char buf[2048];
m_bRecvRuning = true;
while (m_bRecv)
{
struct sockaddr_in fromAddr;
socklen_t len = sizeof(fromAddr);
int n = recvfrom(m_sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&fromAddr, &len);
if (n < 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
else
{
buf[n] = '\0';
if (m_sockfd)
{
m_funcRecvData(fromAddr, buf, n);
}
}
}
m_bRecvRuning = false;
}