以下代码对udp发送和接收都做了封装,在发送和接收前都需要去注册使用的功能,从而做到需要哪个模块才启动哪个模块的功能,避免资源的浪费。
udp发送功能:使用列表和信号量的方式实现异步发送数据,避免主线程发送数据时出现阻塞的情况
udp接收功能:使用select函数可以实现非阻塞方式接收,避免主线程接收数据需要阻塞等待消息的到来
更详细的说明在代码的注释中,如发现问题欢迎批评指正~
udp.h
#pragma once
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <list>
#include <string>
#pragma comment(lib, "WS2_32")
#define CACHE_LENGTH 1024
#define UDP_SERVER 0x02
#define UDP_SEND 0x01
namespace UDP_SERVE {
typedef struct {
u_short port;
std::string ip;
}network_config;
class udp_server
{
public:
udp_server();
~udp_server();
bool Register_Service(size_t, network_config);
bool Cancel_Service(size_t);
bool send_data(const char *);
long receive_data();
public:
char UDP_receive_buffer[CACHE_LENGTH];
private:
bool Register_Server(network_config);
bool Register_Sender(network_config);
bool InitWinsock();
bool Cancel_Sender_Service();
bool Cancel_Server_Service();
static DWORD WINAPI Udp_Send_Fun(LPVOID lpParamter);
private:
volatile bool is_register_Server;
volatile bool is_register_Sender;
fd_set rfd;
struct timeval timeout;
int rev;
SOCKET sockListen;
SOCKADDR_IN addrServer;
SOCKET sockClient;
SOCKADDR_IN addrSender;
HANDLE hThread_sender;
std::list<std::string> udp_send_list;
HANDLE hSemaphore;
};
}
udp.cpp
#include "udp_server.h"
namespace UDP_SERVE {
udp_server::udp_server() :is_register_Server(false), is_register_Sender(false), hThread_sender(NULL)
{
InitWinsock();
}
udp_server::~udp_server()
{
WSACleanup();
}
bool udp_server::Register_Service(size_t type, network_config config)
{
if (type & UDP_SERVER) {
if (!is_register_Server) {
if (!Register_Server(config))
return false;
else
is_register_Server = true;
}
else
printf("UDP_SERVER have already registered\n");
}
if (type & UDP_SEND) {
if (!is_register_Sender) {
if (!Register_Sender(config))
return false;
else
is_register_Sender = true;
}
else {
printf("UDP_SEND have already registered\n");
}
}
return true;
}
bool udp_server::Cancel_Service(size_t type)
{
if (type & UDP_SERVER) {
if (is_register_Server) {
if (!Cancel_Server_Service())
return false;
else
is_register_Server = false;
}
else
printf("UDP_SERVER have already logout\n");
}
if (type & UDP_SEND) {
if (is_register_Sender) {
is_register_Sender = false;
ReleaseSemaphore(hSemaphore, 1, NULL);
if (!Cancel_Sender_Service())
return false;
else
is_register_Sender = false;
}
else
printf("UDP_SEND have already logout\n");
}
return true;
}
bool udp_server::send_data(const char *data)
{
if (is_register_Sender) {
udp_send_list.push_back(std::string(data));
ReleaseSemaphore(hSemaphore, 1, NULL);
}
else {
printf("The Sender service is not registered\n");
return false;
}
return true;
}
long udp_server::receive_data()
{
if (is_register_Server) {
int fromlen = sizeof(struct sockaddr_in);
FD_ZERO(&rfd);
FD_SET(sockListen, &rfd);
int SelectRcv = select(FD_SETSIZE, &rfd, 0, 0, &timeout);
if (SelectRcv == 0) {
return -1;
}
else if (SelectRcv < 0) {
std::cout << "监听失败" << GetLastError() << std::endl;
return -3;
}
else
{
memset(UDP_receive_buffer, '\0', (CACHE_LENGTH) * sizeof(char));
rev = 0;
rev = recvfrom(sockListen, UDP_receive_buffer, (CACHE_LENGTH) * sizeof(char), 0, (struct sockaddr*)&addrServer, &fromlen);
if (rev != SOCKET_ERROR)
{
return rev;
}
else {
return -4;
}
}
}
else {
printf("The Server service is not registered\n");
return -2;
}
}
bool udp_server::Register_Server(network_config config)
{
timeout.tv_sec = 0;
timeout.tv_usec = 0;
rev = 0;
sockListen = socket(AF_INET, SOCK_DGRAM, 0);
if (sockListen == -1)
{
std::cout << "Socket error" << std::endl;
return false;
}
int recvbuf = 1;
setsockopt(sockListen, SOL_SOCKET, SO_RCVBUF, (char*)&recvbuf, sizeof(int));
u_long imode = 1;
rev = ioctlsocket(sockListen, FIONBIO, &imode);
if (rev == SOCKET_ERROR)
{
printf("ioctlsocket failed!");
return false;
}
memset(&addrServer, 0, sizeof(sockaddr_in));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(config.port);
addrServer.sin_addr.s_addr = inet_addr(config.ip.c_str());
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);
addrSender.sin_addr.S_un.S_addr = inet_addr(config.ip.c_str());
addrSender.sin_family = AF_INET;
addrSender.sin_port = htons(config.port);
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(WsaData.wVersion) != 2 || HIBYTE(WsaData.wHighVersion) != 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);
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 -> %s\n", strerror(errno));
}
(p->udp_send_list).pop_front();
}
else {
printf("udp_send_list is empty\n");
}
Sleep(100);
}
printf("Udp_Send_Fun() exit\n");
return 0;
}
}
main.cpp
#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 %s\n", p->UDP_receive_buffer);
}
Sleep(100);
}
return 0;
}
int main()
{
UDP_SERVE::udp_server *p = new UDP_SERVE::udp_server();
UDP_SERVE::network_config config;
config.ip = "0.0.0.0";
config.port = 5600;
if (!p->Register_Service(UDP_SERVER, config)) {
printf("Register_Service error\n");
}
config.ip = "127.0.0.1";
config.port = 5600;
if (!p->Register_Service(UDP_SEND, config)) {
printf("Register_Service error\n");
}
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);
p->Cancel_Service(UDP_SEND);
p->Cancel_Service(UDP_SERVER);
delete p;
system("pause");
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)