QT5实现简单的TCP通信

使用QT的网络套接字需要.pro文件中加入一句:

[cpp]  view plain  copy
  1. QT       += network  

一、客户端

1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:

(1)创建QTcpSocket套接字对象

[cpp]  view plain  copy
  1. socket = new QTcpSocket();  

(2)使用这个对象连接服务器

[cpp]  view plain  copy
  1. socket->connectToHost(IP, port);  

(3)使用write函数向服务器发送数据

[cpp]  view plain  copy
  1. socket->write(data);  

(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

[cpp]  view plain  copy
  1. QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  
  2.   
  3. void MainWindow::socket_Read_Data()  
  4. {  
  5.     QByteArray buffer;  
  6.     //读取缓冲区数据  
  7.     buffer = socket->readAll();  
  8. }  

(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)

[cpp]  view plain  copy
  1. socket->disconnectFromHost();  

2、以下是客户端的例程

首先是mainwindow.h文件:

[cpp]  view plain  copy
  1. //mainwindow.h  
  2. #ifndef MAINWINDOW_H  
  3. #define MAINWINDOW_H  
  4.   
  5. #include <QMainWindow>  
  6. #include <QTcpSocket>  
  7.   
  8. namespace Ui {  
  9. class MainWindow;  
  10. }  
  11.   
  12. class MainWindow : public QMainWindow  
  13. {  
  14.     Q_OBJECT  
  15.   
  16. public:  
  17.     explicit MainWindow(QWidget *parent = 0);  
  18.     ~MainWindow();  
  19.   
  20. private slots:  
  21.   
  22.     void on_pushButton_Connect_clicked();  
  23.   
  24.     void on_pushButton_Send_clicked();  
  25.   
  26.     void socket_Read_Data();  
  27.   
  28.     void socket_Disconnected();  
  29.   
  30. private:  
  31.     Ui::MainWindow *ui;  
  32.     QTcpSocket *socket;  
  33. };  
  34.   
  35. #endif // MAINWINDOW_H  

然后是mainwindow.cpp文件:

[cpp]  view plain  copy
  1. //mainwindow.cpp  
  2. #include "mainwindow.h"  
  3. #include "ui_mainwindow.h"  
  4.   
  5. MainWindow::MainWindow(QWidget *parent) :  
  6.     QMainWindow(parent),  
  7.     ui(new Ui::MainWindow)  
  8. {  
  9.     ui->setupUi(this);  
  10.   
  11.     socket = new QTcpSocket();  
  12.   
  13.     //连接信号槽  
  14.     QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  
  15.     QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);  
  16.   
  17.     ui->pushButton_Send->setEnabled(false);  
  18.     ui->lineEdit_IP->setText("127.0.0.1");  
  19.     ui->lineEdit_Port->setText("8765");  
  20.   
  21. }  
  22.   
  23. MainWindow::~MainWindow()  
  24. {  
  25.     delete this->socket;  
  26.     delete ui;  
  27. }  
  28.   
  29. void MainWindow::on_pushButton_Connect_clicked()  
  30. {  
  31.     if(ui->pushButton_Connect->text() == tr("连接"))  
  32.     {  
  33.         QString IP;  
  34.         int port;  
  35.   
  36.         //获取IP地址  
  37.         IP = ui->lineEdit_IP->text();  
  38.         //获取端口号  
  39.         port = ui->lineEdit_Port->text().toInt();  
  40.   
  41.         //取消已有的连接  
  42.         socket->abort();  
  43.         //连接服务器  
  44.         socket->connectToHost(IP, port);  
  45.   
  46.         //等待连接成功  
  47.         if(!socket->waitForConnected(30000))  
  48.         {  
  49.             qDebug() << "Connection failed!";  
  50.             return;  
  51.         }  
  52.         qDebug() << "Connect successfully!";  
  53.   
  54.         //发送按键使能  
  55.         ui->pushButton_Send->setEnabled(true);  
  56.         //修改按键文字  
  57.         ui->pushButton_Connect->setText("断开连接");  
  58.     }  
  59.     else  
  60.     {  
  61.         //断开连接  
  62.         socket->disconnectFromHost();  
  63.         //修改按键文字  
  64.         ui->pushButton_Connect->setText("连接");  
  65.         ui->pushButton_Send->setEnabled(false);  
  66.     }  
  67. }  
  68.   
  69. void MainWindow::on_pushButton_Send_clicked()  
  70. {  
  71.     qDebug() << "Send: " << ui->textEdit_Send->toPlainText();  
  72.      //获取文本框内容并以ASCII码形式发送  
  73.     socket->write(ui->textEdit_Send->toPlainText().toLatin1());  
  74.     socket->flush();  
  75. }  
  76.   
  77. void MainWindow::socket_Read_Data()  
  78. {  
  79.     QByteArray buffer;  
  80.     //读取缓冲区数据  
  81.     buffer = socket->readAll();  
  82.     if(!buffer.isEmpty())  
  83.     {  
  84.         QString str = ui->textEdit_Recv->toPlainText();  
  85.         str+=tr(buffer);  
  86.         //刷新显示  
  87.         ui->textEdit_Recv->setText(str);  
  88.     }  
  89. }  
  90.   
  91. void MainWindow::socket_Disconnected()  
  92. {  
  93.     //发送按键失能  
  94.     ui->pushButton_Send->setEnabled(false);  
  95.     //修改按键文字  
  96.     ui->pushButton_Connect->setText("连接");  
  97.     qDebug() << "Disconnected!";  
  98. }  

最后是ui的设计:



二、服务器

1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:

(1)创建QTcpSever对象

[cpp]  view plain  copy
  1. server = new QTcpServer();  


(2)侦听一个端口,使得客户端可以使用这个端口访问服务器

[cpp]  view plain  copy
  1. server->listen(QHostAddress::Any, port)  


(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问

[cpp]  view plain  copy
  1. connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);  
  2.   
  3. void MainWindow::server_New_Connect()  
  4. {  
  5.     //获取客户端连接  
  6.     socket = server->nextPendingConnection();  
  7. }  

(4)使用socket的write函数向客户端发送数据

[cpp]  view plain  copy
  1. socket->write(data);  

(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

[cpp]  view plain  copy
  1. QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  
  2.   
  3. void MainWindow::socket_Read_Data()  
  4. {  
  5.     QByteArray buffer;  
  6.     //读取缓冲区数据  
  7.     buffer = socket->readAll();  
  8. }  

(6)取消侦听

[cpp]  view plain  copy
  1. server->close();  

2、以下是服务器的例程

首先是mainwindow.h文件:

[cpp]  view plain  copy
  1. //mainwindow.h  
  2. #ifndef MAINWINDOW_H  
  3. #define MAINWINDOW_H  
  4.   
  5. #include <QMainWindow>  
  6. #include <QTcpServer>  
  7. #include <QTcpSocket>  
  8.   
  9. namespace Ui {  
  10. class MainWindow;  
  11. }  
  12.   
  13. class MainWindow : public QMainWindow  
  14. {  
  15.     Q_OBJECT  
  16.   
  17. public:  
  18.     explicit MainWindow(QWidget *parent = 0);  
  19.     ~MainWindow();  
  20.   
  21. private slots:  
  22.     void on_pushButton_Listen_clicked();  
  23.   
  24.     void on_pushButton_Send_clicked();  
  25.   
  26.     void server_New_Connect();  
  27.   
  28.     void socket_Read_Data();  
  29.   
  30.     void socket_Disconnected();  
  31.   
  32. private:  
  33.     Ui::MainWindow *ui;  
  34.     QTcpServer* server;  
  35.     QTcpSocket* socket;  
  36. };  
  37.   
  38. #endif // MAINWINDOW_H  

然后是mainwindow.cpp文件:

[cpp]  view plain  copy
  1. #include "mainwindow.h"  
  2. #include "ui_mainwindow.h"  
  3.   
  4. MainWindow::MainWindow(QWidget *parent) :  
  5.     QMainWindow(parent),  
  6.     ui(new Ui::MainWindow)  
  7. {  
  8.     ui->setupUi(this);  
  9.   
  10.     ui->lineEdit_Port->setText("8765");  
  11.     ui->pushButton_Send->setEnabled(false);  
  12.   
  13.     server = new QTcpServer();  
  14.   
  15.     //连接信号槽  
  16.     connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);  
  17. }  
  18.   
  19. MainWindow::~MainWindow()  
  20. {  
  21.     server->close();  
  22.     server->deleteLater();  
  23.     delete ui;  
  24. }  
  25.   
  26. void MainWindow::on_pushButton_Listen_clicked()  
  27. {  
  28.     if(ui->pushButton_Listen->text() == tr("侦听"))  
  29.     {  
  30.         //从输入框获取端口号  
  31.         int port = ui->lineEdit_Port->text().toInt();  
  32.   
  33.         //监听指定的端口  
  34.         if(!server->listen(QHostAddress::Any, port))  
  35.         {  
  36.             //若出错,则输出错误信息  
  37.             qDebug()<<server->errorString();  
  38.             return;  
  39.         }  
  40.         //修改按键文字  
  41.         ui->pushButton_Listen->setText("取消侦听");  
  42.         qDebug()<< "Listen succeessfully!";  
  43.     }  
  44.     else  
  45.     {  
  46.         //如果正在连接  
  47.         if(socket->state() == QAbstractSocket::ConnectedState)  
  48.         {  
  49.             //关闭连接  
  50.             socket->disconnectFromHost();  
  51.         }  
  52.         //取消侦听  
  53.         server->close();  
  54.         //修改按键文字  
  55.         ui->pushButton_Listen->setText("侦听");  
  56.         //发送按键失能  
  57.         ui->pushButton_Send->setEnabled(false);  
  58.     }  
  59.   
  60. }  
  61.   
  62. void MainWindow::on_pushButton_Send_clicked()  
  63. {  
  64.     qDebug() << "Send: " << ui->textEdit_Send->toPlainText();  
  65.     //获取文本框内容并以ASCII码形式发送  
  66.     socket->write(ui->textEdit_Send->toPlainText().toLatin1());  
  67.     socket->flush();  
  68. }  
  69.   
  70. void MainWindow::server_New_Connect()  
  71. {  
  72.     //获取客户端连接  
  73.     socket = server->nextPendingConnection();  
  74.     //连接QTcpSocket的信号槽,以读取新数据  
  75.     QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  
  76.     QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);  
  77.     //发送按键使能  
  78.     ui->pushButton_Send->setEnabled(true);  
  79.   
  80.     qDebug() << "A Client connect!";  
  81. }  
  82.   
  83. void MainWindow::socket_Read_Data()  
  84. {  
  85.     QByteArray buffer;  
  86.     //读取缓冲区数据  
  87.     buffer = socket->readAll();  
  88.     if(!buffer.isEmpty())  
  89.     {  
  90.         QString str = ui->textEdit_Recv->toPlainText();  
  91.         str+=tr(buffer);  
  92.         //刷新显示  
  93.         ui->textEdit_Recv->setText(str);  
  94.     }  
  95. }  
  96.   
  97. void MainWindow::socket_Disconnected()  
  98. {  
  99.     //发送按键失能  
  100.     ui->pushButton_Send->setEnabled(false);  
  101.     qDebug() << "Disconnected!";  
  102. }  

最后是ui的设计:



三、运行结果



  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值