C++ UDP连接方式(QT版)

这篇具有很好参考价值的文章主要介绍了C++ UDP连接方式(QT版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

UdpSocket.h

#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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt 利用UDP进行通信

    UDP(用户数据报协议)是一种简单轻量级、不可靠、面向数据报,无连接的传输层协议。而TCP/IP协议却是有连接的 1、网络数据大多为短消息 2、拥有大量客户端 3、对数据安全性无特殊要求 4、网络负担非常重,但对响应速度要求高。 因为upd是无连接的,所以两个通信设备之

    2024年02月03日
    浏览(33)
  • Qt通信TCP/UDP

    qt socket通信,QTcpServer,QTcpSocket,QUdpSocket 链接2 链接3 链接4 QT中不再用套接字进行通信,而是使用连接对

    2024年02月09日
    浏览(40)
  • Qt - UDP网络编程

    UDP(User Datagram Protocol,用户数据报协议) UDP是一个轻量级、不可靠、面向数据报的、无连接的协议,多用于可靠性要求不严格,不是非常重要的传输。 QUdpSocket类继承自QAbstractSocket,用来发送和接收UDP数据报,”Socket”即套接字,套接字即IP地址+端口号。其中IP地址指定了网络

    2024年04月22日
    浏览(104)
  • Qt —UDP通信QUdpSocket 简介 +案例

       UDP是无连接、不可靠、面向数据报(datagram)的协议,可以应用于对可靠性要求不高的场合。与 TCP通信 不同,UDP通信无需预先建立持久的socket连接,UDP每次发送数据报都需要指定目标地址和端口。    QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数据报使用函

    2024年02月10日
    浏览(34)
  • 【QT】TCP/UDP详解及实现

    TCP模型是一个常见的网络协议参考模型,也称为TCP/IP模型或互联网模型。它是指TCP/IP协议族中的一组协议,用于在计算机网络中进行数据通信。TCP模型由四个层次组成,分别是: 应用层(Application Layer): 应用层是最靠近用户的层次,为用户提供各种网络应用服务。 包括常

    2024年02月10日
    浏览(38)
  • Qt实现UDP发送与接收操作

    目录 一、为什么要写这篇文章,因为我就是要另辟蹊径,当然也是汲取了网上大咖们的经验,尽量简洁的进行总结 二、关于接收数据需的条件,需要绑定本地IP地址和端口号,可解释为此时为服务器模式,远端为客户端模式,实现的代码非常简单几行代码可以搞定 三、数据

    2024年02月11日
    浏览(57)
  • Qt 8. UDP客户端通信

    1. 代码 2. 效果 以上代码可以实现UDP收发功能。

    2024年02月13日
    浏览(41)
  • 【QT网络编程】实现UDP协议通信

    Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了 一种无需建立连接就可以发送封装的 IP 数据包的方法 。RFC 768 描述了 UDP。 UDP协议根据消息传送模式可以分为: 单播(Unicast)、组播(Multicast)和广播(

    2024年02月02日
    浏览(56)
  • QT网络通信-TCP、UDP通信

    时间记录:2024/1/17 pro文件添加模块network (1)创建TCP服务器对象 QTcpServer (2)为 QTcpServer 对象的 newConnection 信号绑定槽,用来监听TCP客户端的新连接,有新的客户端连接便会触发此信号 (3)使用 nextPendingConnection 方法获取连接的Tcp客户端对象 QTcpSocket (4)为 QTcpSocket 的 r

    2024年01月18日
    浏览(58)
  • Qt实现UDP单播和组播功能

    UDP是不可靠、无连接的,所以划分为发送方和接收方更好理解  UDP是无连接的,进行单播通信时,只需要绑定接收方端口就行,发送方直接通过接收方的ip和绑定的端口进行通信。发送方可以绑定端口也可以不用绑定端口,不绑定端口的话,系统会随机分配端口。 对于多网卡

    2024年04月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包