QT5实现简单的TCP通信
瑟寒凌风 2018-10-23 10:05:25 9282
收藏 56
分类专栏: QT开发
原文https://blog.youkuaiyun.com/u014695839/article/details/70041771/
这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。
使用QT的网络套接字需要.pro文件中加入一句:
QT += network
一、客户端的编写
1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:
(1)创建QTcpSocket套接字对象
socket = new QTcpSocket();
(2)使用这个对象连接服务器
socket->connectToHost(IP, port);
(3)使用write函数向服务器发送数据
socket->write(data);
(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
-
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
-
void MainWindow::socket_Read_Data()
-
{
-
QByteArray buffer;
-
//读取缓冲区数据
-
buffer = socket->readAll();
-
}
(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)
socket->disconnectFromHost();
2、以下是客户端的例程
首先是mainwindow.h文件:
-
//mainwindow.h
-
#ifndef MAINWINDOW_H
-
#define MAINWINDOW_H
-
#include <QMainWindow>
-
#include <QTcpSocket>
-
namespace Ui {
-
class MainWindow;
-
}
-
class MainWindow : public QMainWindow
-
{
-
Q_OBJECT
-
public:
-
explicit MainWindow(QWidget *parent = 0);
-
~MainWindow();
-
private slots:
-
void on_pushButton_Connect_clicked();
-
void on_pushButton_Send_clicked();
-
void socket_Read_Data();
-
void socket_Disconnected();
-
private:
-
Ui::MainWindow *ui;
-
QTcpSocket *socket;
-
};
-
#endif // MAINWINDOW_H
然后是mainwindow.cpp文件:
-
//mainwindow.cpp
-
#include "mainwindow.h"
-
#include "ui_mainwindow.h"
-
MainWindow::MainWindow(QWidget *parent) :
-
QMainWindow(parent),
-
ui(new Ui::MainWindow)
-
{
-
ui->setupUi(this);
-
socket = new QTcpSocket();
-
//连接信号槽
-
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
-
QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
-
ui->pushButton_Send->setEnabled(false);
-
ui->lineEdit_IP->setText("127.0.0.1");
-
ui->lineEdit_Port->setText("8765");
-
}
-
MainWindow::~MainWindow()
-
{
-
delete this->socket;
-
delete ui;
-
}
-
void MainWindow::on_pushButton_Connect_clicked()
-
{
-
if(ui->pushButton_Connect->text() == tr("连接"))
-
{
-
QString IP;
-
int port;
-
//获取IP地址
-
IP = ui->lineEdit_IP->text();
-
//获取端口号
-
port = ui->lineEdit_Port->text().toInt();
-
//取消已有的连接
-
socket->abort();
-
//连接服务器
-
socket->connectToHost(IP, port);
-
//等待连接成功
-
if(!socket->waitForConnected(30000))
-
{
-
qDebug() << "Connection failed!";
-
return;
-
}
-
qDebug() << "Connect successfully!";
-
//发送按键使能
-
ui->pushButton_Send->setEnabled(true);
-
//修改按键文字
-
ui->pushButton_Connect->setText("断开连接");
-
}
-
else
-
{
-
//断开连接
-
socket->disconnectFromHost();
-
//修改按键文字
-
ui->pushButton_Connect->setText("连接");
-
ui->pushButton_Send->setEnabled(false);
-
}
-
}
-
void MainWindow::on_pushButton_Send_clicked()
-
{
-
qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
-
//获取文本框内容并以ASCII码形式发送
-
socket->write(ui->textEdit_Send->toPlainText().toLatin1());
-
socket->flush();
-
}
-
void MainWindow::socket_Read_Data()
-
{
-
QByteArray buffer;
-
//读取缓冲区数据
-
buffer = socket->readAll();
-
if(!buffer.isEmpty())
-
{
-
QString str = ui->textEdit_Recv->toPlainText();
-
str+=tr(buffer);
-
//刷新显示
-
ui->textEdit_Recv->setText(str);
-
}
-
}
-
void MainWindow::socket_Disconnected()
-
{
-
//发送按键失能
-
ui->pushButton_Send->setEnabled(false);
-
//修改按键文字
-
ui->pushButton_Connect->setText("连接");
-
qDebug() << "Disconnected!";
-
}
最后是ui的设计:
二、服务器编写
1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:
(1)创建QTcpSever对象
server = new QTcpServer();
(2)侦听一个端口,使得客户端可以使用这个端口访问服务器
server->listen(QHostAddress::Any, port)
(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问
-
connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
-
void MainWindow::server_New_Connect()
-
{
-
//获取客户端连接
-
socket = server->nextPendingConnection();
-
}
(4)使用socket的write函数向客户端发送数据
socket->write(data);
(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
-
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
-
void MainWindow::socket_Read_Data()
-
{
-
QByteArray buffer;
-
//读取缓冲区数据
-
buffer = socket->readAll();
-
}
(6)取消侦听
server->close();
2、以下是服务器的例程
首先是mainwindow.h文件:
-
//mainwindow.h
-
#ifndef MAINWINDOW_H
-
#define MAINWINDOW_H
-
#include <QMainWindow>
-
#include <QTcpServer>
-
#include <QTcpSocket>
-
namespace Ui {
-
class MainWindow;
-
}
-
class MainWindow : public QMainWindow
-
{
-
Q_OBJECT
-
public:
-
explicit MainWindow(QWidget *parent = 0);
-
~MainWindow();
-
private slots:
-
void on_pushButton_Listen_clicked();
-
void on_pushButton_Send_clicked();
-
void server_New_Connect();
-
void socket_Read_Data();
-
void socket_Disconnected();
-
private:
-
Ui::MainWindow *ui;
-
QTcpServer* server;
-
QTcpSocket* socket;
-
};
-
#endif // MAINWINDOW_H
然后是mainwindow.cpp文件:
-
#include "mainwindow.h"
-
#include "ui_mainwindow.h"
-
MainWindow::MainWindow(QWidget *parent) :
-
QMainWindow(parent),
-
ui(new Ui::MainWindow)
-
{
-
ui->setupUi(this);
-
ui->lineEdit_Port->setText("8765");
-
ui->pushButton_Send->setEnabled(false);
-
server = new QTcpServer();
-
//连接信号槽
-
connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
-
}
-
MainWindow::~MainWindow()
-
{
-
server->close();
-
server->deleteLater();
-
delete ui;
-
}
-
void MainWindow::on_pushButton_Listen_clicked()
-
{
-
if(ui->pushButton_Listen->text() == tr("侦听"))
-
{
-
//从输入框获取端口号
-
int port = ui->lineEdit_Port->text().toInt();
-
//监听指定的端口
-
if(!server->listen(QHostAddress::Any, port))
-
{
-
//若出错,则输出错误信息
-
qDebug()<<server->errorString();
-
return;
-
}
-
//修改按键文字
-
ui->pushButton_Listen->setText("取消侦听");
-
qDebug()<< "Listen succeessfully!";
-
}
-
else
-
{
-
/*
-
//如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30)
-
if(socket->state() == QAbstractSocket::ConnectedState)
-
{
-
//关闭连接
-
socket->disconnectFromHost();
-
}
-
*/
-
socket->abort();
-
//取消侦听
-
server->close();
-
//修改按键文字
-
ui->pushButton_Listen->setText("侦听");
-
//发送按键失能
-
ui->pushButton_Send->setEnabled(false);
-
}
-
}
-
void MainWindow::on_pushButton_Send_clicked()
-
{
-
qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
-
//获取文本框内容并以ASCII码形式发送
-
socket->write(ui->textEdit_Send->toPlainText().toLatin1());
-
socket->flush();
-
}
-
void MainWindow::server_New_Connect()
-
{
-
//获取客户端连接
-
socket = server->nextPendingConnection();
-
//连接QTcpSocket的信号槽,以读取新数据
-
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
-
QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
-
//发送按键使能
-
ui->pushButton_Send->setEnabled(true);
-
qDebug() << "A Client connect!";
-
}
-
void MainWindow::socket_Read_Data()
-
{
-
QByteArray buffer;
-
//读取缓冲区数据
-
buffer = socket->readAll();
-
if(!buffer.isEmpty())
-
{
-
QString str = ui->textEdit_Recv->toPlainText();
-
str+=tr(buffer);
-
//刷新显示
-
ui->textEdit_Recv->setText(str);
-
}
-
}
-
void MainWindow::socket_Disconnected()
-
{
-
//发送按键失能
-
ui->pushButton_Send->setEnabled(false);
-
qDebug() << "Disconnected!";
-
}
最后是ui的设计: