#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; }