一、说明
首先我们先分析一下:
由于不支持多继承,所以比MFC稍微麻烦了一点,但是QT又具有它自身的优势,那就是信号和槽,我们不用开线程去监听一些事件的触发,会方便许多。
二、 创建一个TCP类
这个类的作用是将客户端和服务端的代码进行一定程度上的统一,便于界面去交互调用。
首先有五个基本方法:
- 连接/启动
- 断开连接
- 是否已经连接
- 发送
- 接收
其次呢,有一个发射的信号和槽,这是为了监听连接状态
最后还有一个Getsocket的方法,这个主要是用来获取socket状态使用
.h文件
#ifndef QTCP_H
#define QTCP_H
#include <QObject>
#include <QTcpSocket>
#include "TcpClient.h"
#include "TcpServer.h"
enum ConnMode{
CLIENT_MODE,
SERVER_MODE
};
class QTCP : public QObject
{
Q_OBJECT
public:
explicit QTCP(QObject *parent = nullptr);
signals:
void Connected();
private slots:
void ConnOK();
public:
QTcpSocket* GetSocket();
public:
bool SetMode(ConnMode mode);
bool Connect(QString ip ,int port);
bool IsConnect();
bool DisConn();
bool Send(QString data);
bool recv(QString &data);
protected:
bool m_IsConnect;
ConnMode m_mode;
TcpServer *m_server;
TcpClient *m_client;
QTcpSocket *m_socket;
};
#endif // QTCP_H
.cpp文件
#include "qtcp.h"
QTCP::QTCP(QObject *parent) : QObject(parent)
{
m_server = new TcpServer(parent);
m_client = new TcpClient(parent);
connect(m_client, &TcpClient::Connected, this, &QTCP::ConnOK);
connect(m_server, &TcpServer::Connected, this, &QTCP::ConnOK);
}
void QTCP::ConnOK()
{
emit Connected();
}
QTcpSocket *QTCP::GetSocket()
{
switch(m_mode){
case CLIENT_MODE:
m_socket = m_client->GetSocket();
break;
case SERVER_MODE:
m_socket = m_server->GetSocket();
break;
}
return m_socket;
}
bool QTCP::SetMode(ConnMode mode)
{
m_mode = mode;
DisConn();
}
bool QTCP::Connect(QString ip, int port)
{
bool ret = false;
switch(m_mode){
case CLIENT_MODE:
ret = m_client->Connect(ip,port);
break;
case SERVER_MODE:
ret = m_server->Connect(ip,port);
break;
}
return ret;
}
bool QTCP::IsConnect()
{
bool ret = false;
switch(m_mode){
case CLIENT_MODE:
ret = m_client->IsConnect();
break;
case SERVER_MODE:
ret = m_server->IsConnect();
break;
}
return ret;
}
bool QTCP::DisConn()
{
if(!IsConnect()){
qWarning()<<"未连接";
return false;
}
bool ret = false;
switch(m_mode){
case CLIENT_MODE:
ret = m_client->DisConn();
break;
case SERVER_MODE:
ret = m_server->DisConn();
m_server->SetDisConn();
break;
}
return ret;
}
bool QTCP::Send(QString data)
{
if(!IsConnect()){
qWarning()<<"未连接";
return false;
}
bool ret = false;
switch(m_mode){
case CLIENT_MODE:
ret = m_client->Send(data);
qInfo()<<"客户端发送数据:"<<data;
break;
case SERVER_MODE:
ret = m_server->Send(data);
qInfo()<<"服务端发送数据:"<<data;
break;
}
return ret;
}
bool QTCP::recv(QString &data)
{
if(!IsConnect()){
qWarning()<<"未连接";
return false;
}
bool ret = false;
switch(m_mode){
case CLIENT_MODE:
ret = m_client->recv(data);
qInfo()<<"客户端接收数据:"<<data;
break;
case SERVER_MODE:
ret = m_server->recv(data);
qInfo()<<"服务端接收数据:"<<data;
break;
}
return ret;
}
三、客户端
创建一个客户端实现上述所有的方法
.h文件
#pragma once
#include <QObject>
#include <QTcpSocket>
class TcpClient : public QObject
{
Q_OBJECT
public:
TcpClient(QObject *parent = nullptr);
~TcpClient();
signals:
void Connected();
public:
bool Connect(QString ip, int port);
bool IsConnect();
bool Send(QString data);
bool recv(QString& data);
bool DisConn();
QTcpSocket* GetSocket();
private:
QTcpSocket* m_socket;
bool m_IsConnect;
};
.cpp文件
#include "TcpClient.h"
TcpClient::TcpClient(QObject *parent):QObject(parent)
{
m_socket = new QTcpSocket();
m_IsConnect = false;
}
TcpClient::~TcpClient()
{
}
bool TcpClient::Connect(QString ip, int port)
{
m_socket->connectToHost(ip,port);
emit Connected();
return true;
}
bool TcpClient::IsConnect()
{
return m_socket->isValid();
}
bool TcpClient::Send(QString data)
{
return m_socket->write(data.toLocal8Bit());
}
bool TcpClient::recv(QString& data)
{
data = QString::fromLocal8Bit(m_socket->readAll());
return true;
}
bool TcpClient::DisConn()
{
m_socket->close();
return true;
}
QTcpSocket* TcpClient::GetSocket()
{
return m_socket;
}
四、服务端
.h文件
#pragma once
#include <QTcpServer>
#include <QTcpSocket>
class TcpServer : public QObject
{
Q_OBJECT
public:
TcpServer(QObject *parent = nullptr);
~TcpServer();
signals:
void Connected();
public:
bool Connect(QString ip, int port);
bool IsConnect();
bool Send(QString data);
bool recv(QString& data);
bool DisConn();
QTcpSocket* GetSocket();
public slots:
void SetConn();
void SetDisConn();
private:
QTcpServer m_Server;
QTcpSocket* m_socket;
bool m_IsConnect;
};
.cpp文件
#include "TcpServer.h"
TcpServer::TcpServer(QObject *parent):QObject(parent)
{
m_IsConnect = false;
m_socket = new QTcpSocket();
}
TcpServer::~TcpServer()
{
}
bool TcpServer::Connect(QString ip, int port)
{
if (!m_Server.listen(QHostAddress::AnyIPv4, port)) {
return false;
}
qInfo()<<"服务器启动成功";
QObject::connect(&m_Server, &QTcpServer::newConnection, this, &TcpServer::SetConn);
return true;
}
bool TcpServer::IsConnect()
{
return m_IsConnect;
}
bool TcpServer::Send(QString data)
{
return m_socket->write(data.toLocal8Bit());
}
bool TcpServer::recv(QString& data)
{
QByteArray b = m_socket->readAll();
data = QString ::fromLocal8Bit(b);
if (data.isEmpty()) {
return false;
}
return true;
}
bool TcpServer::DisConn()
{
m_Server.close();
m_socket->close();
m_socket->disconnectFromHost();
return true;
}
QTcpSocket* TcpServer::GetSocket()
{
return m_socket;
}
void TcpServer::SetConn()
{
if (!m_IsConnect && m_Server.hasPendingConnections()) {
m_socket = m_Server.nextPendingConnection();
emit Connected();
}
m_IsConnect = true;
}
void TcpServer::SetDisConn()
{
m_IsConnect = false;
}
五、说明
pro文件中需要加入network
下一篇:用QT写一个TCP通信助手(四、界面交互)