下图为TCP通信的简单界面,能是实现简单的TCP连接和发送信息,源码在本文第四节(源码含详细注释)
提示:不会使用Qt设计师设计界面的小伙伴点击这里
#ifndef CTCPSERVER_H
#define CTCPSERVER_H
#include
#include
#include
class CTcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit CTcpServer(QTcpServer *parent = nullptr);
//发送信息到已连接的所有客户机
void sendData(QString data);
signals:
//通过该信号传递接收到的数据
void recvDataSignal(QString data);
public slots:
//当有新连接时的槽函数
void newClient();
//当有数据来时的槽函数
void readyReadData();
private:
QList<QTcpSocket *> m_clientList; //存放客户端socket的容器
};
#endif // CTCPSERVER_H
#include "CTcpServer.h"
#include
CTcpServer::CTcpServer(QTcpServer *parent) : QTcpServer(parent)
{
//设置可以连接的ip和端口号(此处为任意ip且端口号为6666的可以连接);若要指定ip,设置第一个参数即可
this->listen(QHostAddress::Any, 8866);
//连接相关的信号槽
connect(this, &CTcpServer::newConnection, this, &CTcpServer::newClient);
}
void CTcpServer::sendData(QString data)
{
//遍历客户端列表,将数据发送到所有客户端中(类似广播)
foreach (QTcpSocket *temp, m_clientList)
{
temp->write(data.toLocal8Bit(), data.length());
}
}
void CTcpServer::newClient()
{
//循环获取客户端socket
while (this->hasPendingConnections())
{
QTcpSocket *clientTemp = this->nextPendingConnection(); //拿到当前的socket
m_clientList.append(clientTemp); //将当前socket添加到列表中(方便操作)
connect(clientTemp, &QTcpSocket::readyRead, this, &CTcpServer::readyReadData);
}
}
void CTcpServer::readyReadData()
{
//拿到发送信号的客户端指针,通过该指针读取数据
QTcpSocket *curClient = dynamic_cast<QTcpSocket *>(sender());
emit recvDataSignal(curClient->readAll());
}
#ifndef CTCPSOCKET_H
#define CTCPSOCKET_H
#include
#include
class CTcpSocket : public QTcpSocket
{
Q_OBJECT
public:
explicit CTcpSocket(QTcpSocket *parent = nullptr);
//通过改函数发送数据
void sendData(QString data);
signals:
//通过该信号传递接收到的数据
void recvDataSignal(QString data);
public slots:
//读取数据的槽函数
void readyReadData();
};
#endif // CTCPSOCKET_H
#include "CTcpSocket.h"
#include
CTcpSocket::CTcpSocket(QTcpSocket *parent) : QTcpSocket(parent)
{
//连接相应槽函数
connect(this, &CTcpSocket::readyRead, this, &CTcpSocket::readyReadData);
//指定ip且端口号为8866, (QHostAddress中指定的ip需本机存在或能连接到才可使用)
this->connectToHost(QHostAddress("192.168.13.1"), 8866);
}
void CTcpSocket::sendData(QString data)
{
this->write(data.toUtf8());
}
void CTcpSocket::readyReadData()
{
emit recvDataSignal(this->readAll());
}
#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H
#include
#include "CTcpServer.h"
#include "CTcpSocket.h"
namespace Ui {
class CMainWindow;
}
class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit CMainWindow(QWidget *parent = 0);
~CMainWindow();
private slots:
void on_connectBtn_clicked(); //连接
void on_sendBtn_clicked(); //发送
void on_appendData(QString data); //将接收的数据显示
private:
Ui::CMainWindow *ui;
CTcpServer *m_server;
CTcpSocket *m_client;
};
#endif // CMAINWINDOW_H
#include "CMainWindow.h"
#include "ui_CMainWindow.h"
CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::CMainWindow)
, m_server(nullptr)
, m_client(nullptr)
{
ui->setupUi(this);
}
CMainWindow::~CMainWindow()
{
if(nullptr != m_server)
{
delete m_server;
m_server = nullptr;
}
if(nullptr != m_client)
{
delete m_client;
m_client = nullptr;
}
delete ui;
}
void CMainWindow::on_connectBtn_clicked()
{
//当连接后直接返回
if("已连接" == ui->connectBtn->text())
return;
if(0 == ui->typeComboBox->currentIndex())
{
m_server = new CTcpServer;
connect(m_server, &CTcpServer::recvDataSignal, this, &CMainWindow::on_appendData);
}
else
{
m_client = new CTcpSocket;
connect(m_client, &CTcpSocket::recvDataSignal, this, &CMainWindow::on_appendData);
}
//设置按钮文本
ui->connectBtn->setText("已连接");
}
void CMainWindow::on_sendBtn_clicked()
{
if(0 == ui->typeComboBox->currentIndex())
{
m_server->sendData(ui->textEdit->toPlainText());
}
else
{
m_client->sendData(ui->textEdit->toPlainText());
}
}
void CMainWindow::on_appendData(QString data)
{
ui->textBrowser->append(data);
}
TCP通信中不像UDP通信中两端都要绑定IP和端口号,并且TCP通信也更加安全。
在本文中不论时服务器还是客户端的IP和端口号都是代码写死的,若是需要能人性化的设置,在界面中添加两个QLineEdit且在自定义的通信类中添加设置IP和端口号的接的,调用该接口并将文本框中的对应值传入即可。若是有兴趣还可实现数据校验、重连、断开连接、指定客户端发送等功能。
自定义UDP类
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除