<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>