175 lines
3.4 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|