UdpSocket.h文章来源:https://www.toymoban.com/news/detail-552259.html
#pragma once
/*
* 警告:此模块由于设计的局限,只能用于短消息通讯,无法收发大数据。
*/
#include <QByteArray>
#include <QString>
#include <QObject>
#include <QThread>
#include <QMutex>
#include "Common_global.h"
class COMMON_EXPORT CSocketBase
{
public:
virtual void onReadReady() = 0;
virtual int getfd() = 0;
};
class COMMON_EXPORT CUdpSocket : public QObject ,public CSocketBase
{
Q_OBJECT
public:
CUdpSocket();
CUdpSocket(int port);
~CUdpSocket();
public:
bool open(int port);
int send(const QByteArray &ar,const QString &addr,int port);
int recv(QByteArray &ar, QString &addr, int &port);
bool close();
signals:
void readyRead();
protected:
void onReadReady();
int getfd() { return m_fd; }
private:
int m_fd;
void* m_datalist;
};
UdpSocket.cpp文章来源地址https://www.toymoban.com/news/detail-552259.html
#include "UdpSocket.h"
#include <winsock2.h>
#include <mstcpip.h>
#include "ModuleMgr.h"
#include <QThread>
//===========================================================================================
class CSocketHandel : protected QThread
{
protected:
CSocketHandel();
~CSocketHandel();
public:
static CSocketHandel * instance();
void addSocket(CSocketBase * p);
void removeSocket(CSocketBase *p);
protected:
void run();
int getfd(int *fds, CSocketBase ** base);
protected:
static void destory();
protected:
bool m_bRuning;
bool m_bQuit;
QMutex m_mutex;
QList<CSocketBase*> m_socketlist;
private:
static CSocketHandel * _instance_;
static bool _bDestoryed_;
};
struct recvData
{
QByteArray data;
QString addr;
int port;
recvData() :port(0) {};
recvData(char * buffer, int szie, const QString &addr_s, int port_s) {
data.append(buffer, szie);
addr = addr_s;
port = port_s;
}
};
class QDataQeue
{
public:
QDataQeue() {};
~QDataQeue() {};
bool isEmpty();
int get(QByteArray &ar,QString &addr,int &port);
void add(char * buffer,int szie,const QString &addr,int port);
private:
QList<recvData> m_datalist;
QMutex m_mutex;
};
bool QDataQeue::isEmpty()
{
return m_datalist.isEmpty();
}
int QDataQeue::get(QByteArray &ar, QString &addr, int &port)
{
QMutexLocker locker(&m_mutex);
if (m_datalist.size() > 0)
{
recvData &d = m_datalist.front();
int n = d.data.size();
ar = d.data;
addr = d.addr;
port = d.port;
m_datalist.pop_front();
return n;
}
return 0;
}
void QDataQeue::add(char * buffer, int szie, const QString &addr, int port)
{
QMutexLocker locker(&m_mutex);
if (m_datalist.size() > 2000)m_datalist.pop_front();
m_datalist.append(recvData(buffer, szie, addr, port));
}
//====================================================================================
CUdpSocket::CUdpSocket():m_fd(-1)
{
m_datalist = new QDataQeue();
}
CUdpSocket::CUdpSocket(int port):m_fd(-1)
{
m_datalist = new QDataQeue();
open(port);
}
CUdpSocket::~CUdpSocket()
{
if (m_fd != -1)close();
QDataQeue * datalist = (QDataQeue*)m_datalist;
if (datalist)delete datalist;
}
bool CUdpSocket::open(int port)
{
m_fd = socket(AF_INET, SOCK_DGRAM, 0); //建立套接字
if (m_fd == INVALID_SOCKET)return false;
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(port);
int s = bind(m_fd, (sockaddr*)&addrSrv, sizeof(SOCKADDR));//绑定套接字
if (0 != s)
{
closesocket(m_fd);
return false;
}
//struct timeval timeout = { 0,nTimeout * 1000 };
int timeout = 3000;
setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
setsockopt(m_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
u_long iMode = 1;//非阻塞模式
ioctlsocket(m_fd, FIONBIO, &iMode);
CSocketHandel *p = CSocketHandel::instance();
if (p)p->addSocket(this);
return true;
}
int CUdpSocket::send(const QByteArray &ar, const QString &addr, int port)
{
SOCKADDR_IN addrSock;
addrSock.sin_addr.S_un.S_addr = inet_addr(addr.toLocal8Bit().data());
addrSock.sin_family = AF_INET;
addrSock.sin_port = htons(port);
int n = ::sendto(m_fd, ar.data(), ar.size(),0, (sockaddr*)&addrSock,sizeof(SOCKADDR_IN));
if (n > 0)return n;
return 0;
}
int CUdpSocket::recv(QByteArray &ar, QString &addr, int &port)
{
QDataQeue * datalist = (QDataQeue*)m_datalist;
if (datalist)
{
return datalist->get(ar, addr, port);
}
return 0;
}
bool CUdpSocket::close()
{
CSocketHandel *p = CSocketHandel::instance();
if (p)p->removeSocket(this);
::closesocket(m_fd);
m_fd = -1;
return true;
}
void CUdpSocket::onReadReady()
{
SOCKADDR_IN addrSock;
memset(&addrSock, 0, sizeof(SOCKADDR_IN));
int len = sizeof(SOCKADDR_IN);
char buffer[4096];
memset(buffer, 0, 4096);
int n = ::recvfrom(m_fd, buffer, 4096, 0, (sockaddr*)&addrSock, &len);
if (n > 0)
{
QString addr = inet_ntoa(addrSock.sin_addr);
int port = ntohs(addrSock.sin_port);
QDataQeue * datalist = (QDataQeue*)m_datalist;
if (datalist)
{
datalist->add(buffer, n, addr, port);
}
emit readyRead();
}
}
//===============================================================================
CSocketHandel * CSocketHandel::_instance_ = NULL;
bool CSocketHandel::_bDestoryed_ = false;
//===============================================================================
CSocketHandel::CSocketHandel()
:m_bRuning(false), m_bQuit(false)
{
this->start();
}
CSocketHandel::~CSocketHandel()
{
if (m_bRuning)
{
m_bQuit = true;
while (m_bRuning)QThread::msleep(100);
}
}
void CSocketHandel::addSocket(CSocketBase * p)
{
m_mutex.lock();
m_socketlist.append(p);
m_mutex.unlock();
}
void CSocketHandel::removeSocket(CSocketBase *p)
{
m_mutex.lock();
m_socketlist.removeAll(p);
m_mutex.unlock();
}
CSocketHandel * CSocketHandel::instance()
{
if (!_instance_)
{
if (!_bDestoryed_)
{
_instance_ = new CSocketHandel();
AtExit(CSocketHandel::destory);
}
}
return _instance_;
}
void CSocketHandel::run()
{
m_bRuning = true;
fd_set readfds;
int fds[64];
CSocketBase * base[64];
struct timeval timeout = { 3,0 };
while (!m_bQuit)
{
FD_ZERO(&readfds);
memset(fds, 0, 64 * sizeof(int));
memset(base, 0, 64 * sizeof(CSocketBase*));
int maxfd = 0;
int n = getfd(fds, base);
for (int i = 0; i < n; i++)
{
FD_SET(fds[i], &readfds);
if (fds[i] > maxfd)maxfd = fds[i];
}
int res = select(n, &readfds, NULL, NULL, &timeout);
if (res > 0)
{
for (int i = 0; i < n; i++)
{
if (FD_ISSET(fds[i], &readfds))
{
base[i]->onReadReady();
}
}
}
}
m_bRuning = false;
}
int CSocketHandel::getfd(int *fds, CSocketBase ** base)
{
QMutexLocker locker(&m_mutex);
int n = 0;
QList<CSocketBase*>::iterator it = m_socketlist.begin();
for (;it != m_socketlist.end(); ++it)
{
int fd = (*it)->getfd();
if (fd != -1)
{
fds[n] = fd;
base[n] = *it;
n++;
}
}
return n;
}
void CSocketHandel::destory()
{
if (_instance_)
{
delete _instance_;
_bDestoryed_ = true;
}
}
到了这里,关于C++ UDP连接方式(QT版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!