2023年7月15日发(作者:)
window下cc++异步发送udp和⾮阻塞的⽅式接收udp的类封装以下代码对udp发送和接收都做了封装,在发送和接收前都需要去注册使⽤的功能,从⽽做到需要哪个模块才启动哪个模块的功能,避免资源的浪费。udp发送功能:使⽤列表和信号量的⽅式实现异步发送数据,避免主线程发送数据时出现阻塞的情况udp接收功能:使⽤select函数可以实现⾮阻塞⽅式接收,避免主线程接收数据需要阻塞等待消息的到来更详细的说明在代码的注释中,如发现问题欢迎批评指正~udp.h#pragma once#include #include
注册服务 // param:
参数⼀/说明要注册的服务的类型(UDP_SERVER为UDP接收,UDP_SEND为UDP发送)
参数⼆/配置的⽹络信息
// return:
注册成功或者已注册返回true,注册失败返回false bool Register_Service(size_t, network_config); // desc:
注销服务 // param:
参数⼀/说明要注销的服务的类型(UDP_SERVER为UDP接收,UDP_SEND为UDP发送) // return:
注销成功或者已注册返回true,注销失败返回false bool Cancel_Service(size_t); // desc:
发送数据 // param:
参数⼀/要发送的数据 // return:
发送成功返回true,发送失败返回false bool send_data(const char *); // desc:
⾮阻塞接收数据 // param: NULL // return:
没接收到数据返回-1,接收服务未注册返回-2,监听失败返回-3,recvfrom接收失败返回-4,成功则返回接收到的字符数 long receive_data(); public: char UDP_receive_buffer[CACHE_LENGTH]; //接收缓冲区 char UDP_receive_buffer[CACHE_LENGTH]; //接收缓冲区 private: // desc:
注册接收服务 // param:
参数⼀/配置的⽹络信息
// return:
注册成功返回true,注册失败返回false bool Register_Server(network_config); // desc:
注册发送服务 // param:
参数⼀/配置的⽹络信息
// return:
注册成功返回true,注册失败返回false bool Register_Sender(network_config); // desc:
启动WinSock2 // param: NULL // return:
启动成功返回true,启动失败返回false bool InitWinsock(); // desc:
注销发送服务 // param: NULL // return:
取消成功返回true,取消失败返回false bool Cancel_Sender_Service(); // desc:
注销接收服务 // param: NULL // return:
取消成功返回true,取消失败返回false bool Cancel_Server_Service(); // desc:
发送端多线程函数 // param: udp_server类指针 // return: NULL static DWORD WINAPI Udp_Send_Fun(LPVOID lpParamter); private: volatile bool is_register_Server; //Server是否初始化标识位 volatile bool is_register_Sender; //Sender是否初始化标识位 fd_set rfd; //描述符集
这个将⽤来测试有没有⼀个可⽤的连接 struct timeval timeout; //定时
int rev; SOCKET sockListen; //接收者socket SOCKADDR_IN addrServer; //接收端⽹络信息 SOCKET sockClient; //发送端socket SOCKADDR_IN addrSender; //发送端⽹络信息 HANDLE hThread_sender; //发送端多线程句柄 std::list
u_long imode = 1; rev = ioctlsocket(sockListen, FIONBIO, &imode); if (rev == SOCKET_ERROR) { printf("ioctlsocket failed!"); //closesocket(sockListen); //WSACleanup(); return false; } memset(&addrServer, 0, sizeof(sockaddr_in)); _family = AF_INET; _port = htons(); //监听端⼝ _addr.s_addr = inet_addr(.c_str()); //INADDR_ANY if (0 != ::bind(sockListen, (struct sockaddr*)&addrServer, sizeof(struct sockaddr))) { std::cout << "recv_bind()失败,error: " << GetLastError() << std::endl; return false; } return true; } bool udp_server::Register_Sender(network_config config) { sockClient = socket(AF_INET, SOCK_DGRAM, 0); _addr.S_un.S_addr = inet_addr(.c_str()); _family = AF_INET; _port = htons(); hThread_sender = CreateThread(NULL, 0, Udp_Send_Fun, this, 0, NULL); //创建发送⼦线程 hSemaphore = CreateSemaphore(NULL, 0, 100, NULL); //创建信号量 return true; } bool udp_server::InitWinsock() { int Error; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); Error = WSAStartup(VersionRequested, &WsaData); if (Error != 0) { return false; } else { if (LOBYTE(on) != 2 || HIBYTE(ersion) != 2) { WSACleanup(); return false; } } return true; } bool udp_server::Cancel_Sender_Service() { WaitForMultipleObjects(1, &hThread_sender, TRUE, INFINITE); CloseHandle(hSemaphore); CloseHandle(hThread_sender); closesocket(sockClient); return true; } bool udp_server::Cancel_Server_Service() { closesocket(sockListen); return false; } DWORD udp_server::Udp_Send_Fun(LPVOID lpParamter) { udp_server *p = (udp_server *)lpParamter; while (1) { WaitForSingleObject(p->hSemaphore, INFINITE); //阻塞等待信号,直到信号量为signal状态。函数执⾏后信号量⾃动减1 if (!p->is_register_Sender) { break; } if (!(p->udp_send_list).empty()) { if (-1 == sendto(p->sockClient, (p->udp_send_list).front().c_str(), (p->udp_send_list).front().size(), 0, (SOCKADDR*)&(p->addrSender), sizeof(SOCKADDR))) { //发送数据 printf("UDP SendTo error -> %sn", strerror(errno)); } (p->udp_send_list).pop_front(); //数据出列 } else { printf("udp_send_list is emptyn"); } Sleep(100); } printf("Udp_Send_Fun() exitn"); return 0; }}#include "udp_server.h"//轮询查看有没有消息到来DWORD WINAPI test_Func(LPVOID lpParamter) { UDP_SERVE::udp_server *p = (UDP_SERVE::udp_server *)lpParamter; while (1) { long l_buf = p->receive_data(); //接收错误 if (-1 > l_buf) { break; } //未接收到数据 else if (l_buf == -1) { continue; } //接收到数据 else { printf("len %ld, ", l_buf); printf("data %sn", p->UDP_receive_buffer); } Sleep(100); } return 0;}int main(){ UDP_SERVE::udp_server *p = new UDP_SERVE::udp_server(); //设置接收udp模块的信息 UDP_SERVE::network_config config; = "0.0.0.0"; = 5600; //注册接收udp模块 if (!p->Register_Service(UDP_SERVER, config)) { printf("Register_Service errorn"); } //设置发送udp模块的信息 = "127.0.0.1"; = 5600; //注册发送udp模块 if (!p->Register_Service(UDP_SEND, config)) { printf("Register_Service errorn"); } //创建测试线程 CreateThread(NULL, 0, test_Func, p, 0, NULL); Sleep(1000); //发送数据 std::string data = "ggrerrrrr"; p->send_data(data.c_str()); data = "gg1"; p->send_data(data.c_str()); data = "gg2"; p->send_data(data.c_str()); data = "gg3"; p->send_data(data.c_str()); data = "gg4"; p->send_data(data.c_str()); data = "gg5"; p->send_data(data.c_str()); data = "gg6"; p->send_data(data.c_str()); data = "gg7"; p->send_data(data.c_str()); data = "gg8"; p->send_data(data.c_str()); Sleep(1000);
//注销发送udp模块 p->Cancel_Service(UDP_SEND); //注销接收udp模块 p->Cancel_Service(UDP_SERVER); delete p; system("pause"); return 0;}
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1689408916a243357.html
评论列表(0条)