QTcpServer使用信号槽单线程方式直接处理连进来的客户端(短连接或少数据处理)

引用一下这位大哥的说法:

 

  • u010111033

    2016-10-25 17:511楼
  • QTcpServer使用,在我的总结里这么来好点:
    1、直接继承QTcpServer(适合一端口接收多个客户端等方式),在虚函数incomeingconnection()里面写收到连接后的动作,短连接的话直接写socket收发就行,长连接的话写在Thread里面的socket收发;
    2、一对一情况下,直接按照信号与槽方式继承于QObject,怎么写都可以,这种教程就多了

  • //头文件
    #pragma once
    #include <qtcpserver.h>
    #include <qtcpsocket.h>
    #include <qmap.h>
    
    class TcpServer : public QObject
    {
    	Q_OBJECT
    public:
    	TcpServer(const QString &ip, int port);
    	~TcpServer();
    
    private slots:
    	void NewConnection();
    	void ReadAndParseData();
    	void SocketErr(QAbstractSocket::SocketError socketError);
    	void SocketDisconn();
    private:
    	QTcpServer *m_tcpServer;
    	QMap<QTcpSocket*, QString> m_socketMapData;
    };
    
    // cpp文件
    #include <qtcpsocket.h>
    #include <qthread.h>
    #include "TcpServer.h"
    #include "log.h"
    #include "FaceHttp.h"
    
    
    TcpServer::TcpServer(const QString &ip, int port)
    {
    	m_tcpServer = new QTcpServer();
    	connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
    
    	bool bsucc;
    	if (ip.isEmpty())
    	{
    		bsucc = m_tcpServer->listen(QHostAddress::AnyIPv4, port);
    	}
    	else
    	{
    		bsucc = m_tcpServer->listen(QHostAddress(ip), port);
    	}
    
    	WLog(LOG_DEBUG,"listen bsucc[%d],ip[%s] port[%d] errstr[%s]", bsucc,ip.toLocal8Bit().data(),
    		port,m_tcpServer->errorString().toLocal8Bit().data());
    }
    
    TcpServer::~TcpServer()
    {
    	if (m_tcpServer != NULL)
    	{
    		m_tcpServer->close();
    		delete m_tcpServer;
    		m_tcpServer = NULL;
    	}
    }
    
    /*
     连接进来的socket如果是短连接,则直接用信号槽处理即可,
     如果是长连接,或者接收发送数据比较耗时,则需要分别写一个类从qtcpserver和qtcpsocket继承下来,并重载qtcpserver的incomingConnection()
     函数,在incomingConnection()函数内创建继承的qtcpsocket类。
     以下代码是直接信号槽处理的
    */
    void TcpServer::NewConnection()
    {
    	// 每连进来一个,就起一个线程处理,断开连接则退出线程
    	if (m_tcpServer->hasPendingConnections()) // 是否有等待连接的
    	{
    		QTcpSocket *socket = m_tcpServer->nextPendingConnection(); // 从列表中取出等待连接的
            //socket->setParent(NULL); // 否则会提示Cannot move object with a parent
             //socket->setParent(NULL); // 否则会提示Cannot move object with a parent
    		//QThread *thread = new QThread(socket); // 以socket为父类,当socket断开释放内存时也会相应的释放thread分配的内存
    		//socket->moveToThread(thread);  //没法以此种方式移到线程,否则socket创建与使用将会在不同线程,结果将是socket并没有成功移到线程内 
    
    		connect(socket, SIGNAL(disconnected()), socket, SLOT(SocketDisconn()));
    		//connect(socket, SIGNAL(disconnected()), thread, SLOT(quit()));
    		connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
    		connect(socket, SIGNAL(readyRead()), this, SLOT(ReadAndParseData()));
    		WLog(LOG_DEBUG, "new comming,socket[%d],ip[%s] port[%d]\n", socket->socketDescriptor(), socket->peerAddress().toString().toLocal8Bit().data(), socket->peerPort());
    		//thread->start(); // 启动线程
    	}
    }
    
    void TcpServer::ReadAndParseData()
    {
    	QTcpSocket *socket = (QTcpSocket*)sender();
    	QString str = m_socketMapData[socket];  //如果map中之前没有这个socket,则会以这个socket创建一个新的键值对,返回一个空QString
    	QString recvStr = socket->readAll();
    	str += recvStr;
    	// 对数据的处理
    	m_socketMapData[socket] = str;	
    }
    
    void TcpServer::SocketErr(QAbstractSocket::SocketError socketError)
    {
    	QTcpSocket *socket = (QTcpSocket*)sender();
    	WLog(LOG_ERR, "socket[%d] err[%s]", socket->socketDescriptor(), socket->errorString().toLocal8Bit().data());
    }
    
    void TcpServer::SocketDisconn()
    {
    	QTcpSocket* socket = (QTcpSocket*)sender();
    	WLog(LOG_DEBUG, "socket[%d][%s] close", socket->socketDescriptor(), socket->peerAddress().toString().toLocal8Bit().data());
    	if (m_socketMapData.count(socket) > 0)
    	{
    		m_socketMapData.remove(socket);
    		delete socket;
    		socket = NULL;
    	}
    }
    
  • 	
  •  
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt是一种流行的跨平台应用程序开发框架,其中包含了一些用于网络通信的类。其中之一就是QtQTcpServer类,它提供了一种简单的方式来创建一个TCP服务器。 使用QTcpServer类,我们可以方便地实现多个客户端连接到服务器的功能。首先,我们需要创建一个QTcpServer对象,并调用其listen()函数来监听指定的IP地址和端口。当有客户端连接到服务器时,QTcpServer会自动触发一个新的连接信号newConnection(),我们可以使用一个函数来处理这个信号。 在函数中,我们可以调用QTcpServer的nextPendingConnection()函数来获取新的连接,然后将其保存到一个QList或QVector中,以便于对它们进行管理。每个连接都代表一个与客户端的通信通道,我们可以通过调用QTcpSocket的相应函数来读取和写入数据。 为了处理多个客户端连接,我们可以使用Qt的事件循环机制。在每次循环中,我们可以遍历保存连接的列表,检查是否有新的数据可读取。我们可以使用QIODevice的readyRead()信号来实现这一功能,当有数据可读取时,我们可以调用QTcpSocket的相应函数来读取数据。 另外,我们还可以设置QTcpServer的maxPendingConnections属性来限制同时连接到服务器的客户端数量。当达到最大连接数时,后续的连接请求会被服务器忽略。 总的来说,使用QTcpServer实现多个客户端连接的功能相对简单,我们只需要注意管理连接对象和使用事件循环机制来处理数据即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值