QTcpsocket 使用 模板

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">常用代码,在这里记录一下,方便以后查找</span>

客户端

Client.h

ifndef CLIENT_H
#define CLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QTimer>
#include <QTime>

class Client:public QObject
{
    Q_OBJECT
public:
	Client(QString ip,int port);
	~Client();

	void connectServer();
	void sendCallInfo(QString& info);
signals:
	void message(QString info);
	protected slots:
    void readMessage();
    //发送并检测心跳包,判断是否连接状态,断开则重连
    void sendAndCheckHeartPacket();
	void error(QAbstractSocket::SocketError socketError);
    void connectToHost();
    void disConnectToHost();

protected:
    QTimer m_timer;  //定时发送心跳包
    int m_time;    //用于计时,看没有收到心跳包的秒数
    QTcpSocket* m_tcpSocket;
    QByteArray m_outBlock;
    QString m_ip;
    int m_port;
    bool m_bConnectToHost;
    short m_blockSize;
};

#endif // CLIENT_H

Client.cpp

#include "client.h"
#include <QDebug>
#include <QSettings>
#include <QDataStream>
#include <simplelog.h>


Client::Client(QString ip, int port)
{
	m_tcpSocket = NULL;
	m_ip = ip;
	m_port = port;
	m_bConnectToHost = false;
	m_blockSize = 0;
    connect(&m_timer,SIGNAL(timeout()),this,SLOT(sendAndCheckHeartPacket()));
	m_timer.start(1000);
	m_time = 0; 
	m_blockSize = 0;
}

Client::~Client()
{
    m_timer.stop();
    if(m_tcpSocket)delete m_tcpSocket;
}

void Client::connectServer()
{
    if(m_timer.isActive())m_timer.stop();
    if(m_tcpSocket != NULL)
    {
		LOGWRANING(QString::fromLocal8Bit("tcp reconnect!"));
        disconnect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
        disconnect(m_tcpSocket,SIGNAL(connected()),this,SLOT(connectToHost()));
        disconnect(m_tcpSocket,SIGNAL(disconnected()),this,SLOT(disConnectToHost()));
        delete m_tcpSocket;
    }
    m_tcpSocket = new QTcpSocket(this);
    connect(m_tcpSocket,SIGNAL(connected()),this,SLOT(connectToHost()));
    connect(m_tcpSocket,SIGNAL(disconnected()),this,SLOT(disConnectToHost()));
	connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
    m_tcpSocket->abort();
    m_tcpSocket->connectToHost(m_ip,m_port);
    qDebug() << "connect to: " << m_ip << "," << m_port;
    connect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
    m_timer.start(1000);
    m_time = 0;
    m_blockSize = 0;
}


void Client::sendCallInfo(QString& info)
{
	if (!m_bConnectToHost)
	{
		qDebug() << "the socket is available\n";
		return;
	}
	QDataStream sendOut(&m_outBlock, QIODevice::WriteOnly);
	sendOut.setVersion(QDataStream::Qt_4_6);
	sendOut << (quint16)0;
	sendOut << uchar(0xFE) << info << uchar(0xAA);
	sendOut.device()->seek(0);
	sendOut << (quint16)(m_outBlock.size() - sizeof(quint16));
	m_tcpSocket->write(m_outBlock);
	m_outBlock.resize(0);
}

void Client::connectToHost()
{
    qDebug() << "success to connect to server\n";
    m_bConnectToHost = true;
}

void Client::disConnectToHost()
{
    qDebug() << "disconnect from host\n";
	if (m_tcpSocket)
	{
		LOGWRANING(QString::fromLocal8Bit("disconnect from host").arg(m_tcpSocket->errorString()));
	}
    m_bConnectToHost = false;
}

void Client::readMessage()
{
    QDataStream in(m_tcpSocket);
    in.setVersion(QDataStream::Qt_4_6);
   // qDebug() << "socket size: " << m_tcpSocket->readBufferSize();
    if(m_blockSize==0) //如果是刚开始接收数据
    {
        //判断接收的数据是否有两字节,也就是文件的大小信息
        //如果有则保存到blockSize变量中,没有则返回,继续接收数据
        if(m_tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;
        in >> m_blockSize;
    }
    //如果没有得到全部的数据,则返回,继续接收数据
    if(m_tcpSocket->bytesAvailable() < m_blockSize) return;
    unsigned char _startFlag;
    unsigned char _endFlag;
    in >> _startFlag;
   // qDebug() << _startFlag << "," << m_tcpSocket->readBufferSize();
    if(_startFlag == 0XFF)
    {
        in >> _endFlag;
        if(_endFlag == 0xAA)
        {
            //if(m_location == _location)qDebug() << "receive heart package,connection is alive";
            m_time = 0;//重新开始计时
        }
    }
	else if (_startFlag == 0XFE)
    {
		QString info;
		in >> info;
		in >> _endFlag;
		if (_endFlag == 0xAA)
		{
			emit message(info);
		}
    }
    m_blockSize = 0;
}

void Client::sendAndCheckHeartPacket()
{
    if(m_time >= 10 || !m_bConnectToHost)//如果40秒钟未收到服务器返回的心跳包,重连
    {
		if (m_tcpSocket)
		{
			LOGWRANING(QString::fromLocal8Bit("disconnect from host").arg(m_tcpSocket->errorString()));
		}
		else
			LOGWRANING(QString::fromLocal8Bit("检查到连接断开:time:%1,%2").arg(m_time).arg(m_bConnectToHost));
        connectServer();
    }
    m_time += 1;
    if(!m_tcpSocket)return;
    if(m_tcpSocket->isValid() && m_bConnectToHost)
    {
        QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
        sendOut.setVersion(QDataStream::Qt_4_6);
        sendOut<<(quint16) 0;
        sendOut << uchar(0xFF) << uchar(0xAA);
        sendOut.device()->seek(0);
        sendOut<<(quint16) (m_outBlock.size() - sizeof(quint16));
        m_tcpSocket->write(m_outBlock);
        m_outBlock.resize(0);
    }
}

void Client::error(QAbstractSocket::SocketError socketError)
{
	if (m_tcpSocket)
		LOGERROR(QString::fromLocal8Bit("SOCKET 发生错误:%1,%2").arg(socketError).arg(m_tcpSocket->errorString()));
}

服务端

server.h

#ifndef SERVER_H
#define SERVER_H

#include <QObject>
#include <QJsonObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QTime>
#include <QSettings>

class ClientRef;
class Server:public QObject
{
    Q_OBJECT
public:
	Server(int port);
	~Server(){};

public:
	void sendCallInfo(QString& info);

protected slots:
    virtual void newConnect();
    void destroyConnection(ClientRef* ref);
protected:
    QTcpServer* m_tcpServer;
    QList<ClientRef*> m_connectClients;
};


class ClientRef : public QObject
{
    Q_OBJECT
public:
	ClientRef(QTcpSocket* socket,Server* _parent);
	~ClientRef();

	void sendCallInfo(QString& info);
signals:
	void destroy(ClientRef* ref);
public slots:
    void readMessage();
    //检测心跳包,判断是否连接状态,断开则重连
    void checkHeartPacket();
    void disConnectSocket();
	void error(QAbstractSocket::SocketError socketError);
protected:
	friend class Server;
    QByteArray m_outBlock;
    QTcpSocket* m_tcpSocket;
    QTimer m_timer;  //
    int m_time;      //用于计时,看多久没有收到心跳包de miaoshu
    bool m_bSocketAvailable;
    Server* m_parent;
    short m_blockSize;
};

#endif // SERVER_H

server.cpp

#include "server.h"
#include <iostream>
#include <QDebug>
#include <QTime>
#include "simplelog.h"
#include "persession.h"
#include <QDataStream>


Server::Server(int port)
{
    m_tcpServer = new QTcpServer(this);
    connect(m_tcpServer,SIGNAL(newConnection()),this,SLOT(newConnect())); //新连接信号触发,调用newConnect()槽函数,这个跟信号函数一样,其实你可以随便取}
	if (m_tcpServer->listen(QHostAddress::Any, port))
	{
		LOGINFO(QString::fromLocal8Bit("监听端口%1成功").arg(port));
	}
}


void Server::sendCallInfo(QString& info)
{
	static PerSession sessionSaved;
	PerSession& sessionReceived = PerSession::fromPackage(info);
	if (sessionSaved.callID() == sessionReceived.callID())
	{
		if (sessionSaved.endReason() == sessionReceived.endReason())
		{
			//保证发送的状态信息是不断向前的
			if (sessionReceived.findCaller()->curState() <= sessionSaved.findCaller()->curState() && sessionReceived.findFirstCalled()->curState() <= sessionSaved.findFirstCalled()->curState())
			{
				return;
			}
		}
	}
	for (int i = 0; i < m_connectClients.size(); i++)
	{
		m_connectClients[i]->sendCallInfo(info);
	}
	sessionSaved = sessionReceived;
}

void Server::newConnect()
{
	ClientRef* _cr = new ClientRef(m_tcpServer->nextPendingConnection(),this);
	connect(_cr, SIGNAL(destroy(ClientRef*)), this, SLOT(destroyConnection(ClientRef*)));
    m_connectClients.append(_cr);
	LOGINFO(QString("new connect comming to :%1").arg(_cr->m_tcpSocket->localAddress().toString()));
}


void Server::destroyConnection(ClientRef* ref)
{
    if(m_connectClients.contains(ref))
    {
		LOGWRANING(QString::fromLocal8Bit("移除 %1 的连接").arg(ref->m_tcpSocket->localAddress().toString()));
        m_connectClients.removeOne(ref);
		ref->deleteLater();
		//delete ref;
    }
}


////////////////////////////////////////////////////////////////////////////////////
ClientRef::ClientRef(QTcpSocket* socket, Server* _parent)
{
	m_tcpSocket = socket;
	connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage())); //有可读的信息,触发读函数槽
	connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(disConnectSocket()));
	connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); 
	connect(&m_timer,SIGNAL(timeout()),SLOT(checkHeartPacket()));
     m_blockSize = 0;
     m_outBlock.resize(0);
     m_parent = _parent;
     m_time = 0;
	 m_bSocketAvailable = true;
	 m_timer.start(1000);
}

ClientRef::~ClientRef()
{
    m_timer.stop();
}


void ClientRef::sendCallInfo(QString& info)
{
	if (!m_bSocketAvailable)
	{
		qDebug() << "the socket is available\n";
		return;
	}
	QDataStream sendOut(&m_outBlock, QIODevice::WriteOnly);
	sendOut.setVersion(QDataStream::Qt_4_6);
	sendOut << (quint16)0;
	sendOut << uchar(0xFE) << info << uchar(0xAA);
	sendOut.device()->seek(0);
	sendOut << (quint16)(m_outBlock.size() - sizeof(quint16));
	m_tcpSocket->write(m_outBlock);
	m_outBlock.resize(0);
}

void ClientRef::disConnectSocket()
{  
	LOGERROR(m_tcpSocket->localAddress().toString() + " disconnect");
    m_bSocketAvailable = false;
}

void ClientRef::error(QAbstractSocket::SocketError socketError)
{
	if (m_tcpSocket)
		LOGERROR(QString::fromLocal8Bit("SOCKET 发生错误:%1,%2").arg(socketError).arg(m_tcpSocket->errorString()));
}



void ClientRef::checkHeartPacket()
{
    if(m_time >= 10 || !m_bSocketAvailable)//如果10秒钟未收到服务器返回的心跳包,重连
    { 
		LOGWRANING(QString::fromLocal8Bit("检查到连接断开:time:%1,%2").arg(m_time).arg(m_tcpSocket->errorString()));
        emit destroy(this);//删除自身
		return;
    }
    m_time += 1;
}


void ClientRef::readMessage() //读取信息
{
    QDataStream in(m_tcpSocket);
    in.setVersion(QDataStream::Qt_4_6);
    if(m_blockSize==0) //如果是刚开始接收数据
    {
        //判断接收的数据是否有两字节,也就是文件的大小信息
        //如果有则保存到blockSize变量中,没有则返回,继续接收数据
        if(m_tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;
        in >> m_blockSize;
    }
    //如果没有得到全部的数据,则返回,继续接收数据
    if(m_tcpSocket->bytesAvailable() < m_blockSize) return;
    unsigned char _startFlag;
    unsigned char _endFlag;
    in >> _startFlag;
    if(_startFlag == 0XFF)
    {
        in >> _endFlag;
        if(_endFlag == 0xAA)
        {
            QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
            sendOut.setVersion(QDataStream::Qt_4_6);
            sendOut<<(quint16) 0;
            sendOut << uchar(0xFF) << uchar(0xAA);
            sendOut.device()->seek(0);
            sendOut<<(quint16) (m_outBlock.size() - sizeof(quint16));
            m_tcpSocket->write(m_outBlock);
            m_outBlock.resize(0);
            m_time = 0;
        }
    }
	else if (_startFlag == 0XFE)
    {
		QString info;
		in >> info;
		in >> _endFlag;
		if (_endFlag == 0xAA)
		{
			m_parent->sendCallInfo(info);
		}
    }

    m_blockSize = 0;
}






</pre><pre>

猜你喜欢

转载自blog.csdn.net/stafniejay/article/details/51699502
今日推荐