This commit is contained in:
azw 2023-04-15 01:13:39 +00:00
parent 73a4706673
commit 50341c6846
2 changed files with 179 additions and 0 deletions

152
a8/udplistener.cc Normal file
View File

@ -0,0 +1,152 @@
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <netinet/tcp.h>
#include <string>
#include <functional>
#include <thread>
#include <a8/udplistener.h>
namespace a8
{
struct UdpListenerImpl
{
a8::UdpListener* master = nullptr;
int listen_socket = -1;
std::thread* worker_thread = nullptr;
volatile bool shutdown = false;
bool IsActive()
{
return listen_socket != -1;
}
void SetActive(bool active)
{
if (active) {
if (IsActive()) {
return;
}
if (!worker_thread) {
shutdown = false;
worker_thread = new std::thread(&a8::UdpListenerImpl::WorkerThreadProc, this);
}
} else {
if (IsActive()) {
ActiveStop();
}
}
}
bool ActiveStart()
{
listen_socket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (listen_socket == -1){
if (master->on_error) {
master->on_error(master, errno);
}
return false;
}
// TIME_WAIT - argh
int on = 1;
if (::setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1 ){
//return false;
}
sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(master->bind_address.c_str());
sa.sin_port = htons(master->bind_port);
if (::bind(listen_socket, (sockaddr*)&sa, sizeof(sa)) < 0) {
if (master->on_error) {
master->on_error(master, errno);
}
::close(listen_socket);
listen_socket = -1;
return false;
}
return true;
}
void ActiveStop()
{
if(listen_socket != -1){
::close(listen_socket);
listen_socket = -1;
}
if (worker_thread) {
shutdown = true;
worker_thread->join();
delete worker_thread;
worker_thread = NULL;
}
}
void WorkerThreadProc()
{
if(!ActiveStart())
return;
struct sockaddr_in destAddr;
socklen_t addrLen = sizeof(sockaddr_in);
char recv_buf[1024 * 64];
int buflen = sizeof(recv_buf);
while (!shutdown) {
int ret = ::recvfrom(listen_socket,
recv_buf,
buflen,
0,
(struct sockaddr*)&destAddr,
(socklen_t*)&addrLen);
if(ret > 0){
master->OnSocketRead(recv_buf, ret);
}
}
}
};
UdpListener::UdpListener()
{
impl_ = new a8::UdpListenerImpl();
impl_->master = this;
}
UdpListener::~UdpListener()
{
delete impl_;
impl_ = nullptr;
}
void UdpListener::OnSocketRead(char*, unsigned int)
{
}
void UdpListener::Open()
{
if (!IsActive()) {
impl_->SetActive(true);
}
}
void UdpListener::Close()
{
if (IsActive()) {
impl_->SetActive(false);
}
}
bool UdpListener::IsActive()
{
return impl_->IsActive();
}
}

27
a8/udplistener.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
namespace a8
{
struct UdpListenerImpl;
class UdpListener
{
public:
std::function<void (a8::UdpListener*, int error_id)> on_error;
std::string bind_address;
unsigned short bind_port = 0;
public:
UdpListener();
~UdpListener();
virtual void OnSocketRead(char*, unsigned int);
void Open();
void Close();
bool IsActive();
private:
a8::UdpListenerImpl* impl_ = nullptr;
};
}