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
  • 		//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;
    	}
    }
    

猜你喜欢

转载自blog.csdn.net/qqwangfan/article/details/78192810