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

  1. QT += network

客户端

Qt TCP/IP网络通讯 - 图2

客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:
  1. 创建QTcpSocket套接字对象
  1. socket = new QTcpSocket();
  1. 使用这个对象连接服务器
  1. socket->connectToHost(IP, port);
  1. 使用write函数向服务器发送数据
  1. socket->write(data);
  1. 当socket接收缓冲区有新数据到来时,会发出readyRead()信号,因此为该信号添加槽函数以读取数据
  1. QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
  2. void MainWindow::socket_Read_Data()
  3. {
  4. QByteArray buffer;
  5. //读取缓冲区数据
  6. buffer = socket->readAll();
  7. }
  1. 断开与服务器的连接
  1. socket->disconnectFromHost();

mainwindow.h文件

  1. //mainwindow.h
  2. #ifndef MAINWINDOW_H
  3. #define MAINWINDOW_H
  4. #include <QMainWindow>
  5. #include <QTcpSocket>
  6. namespace Ui {
  7. class MainWindow;
  8. }
  9. class MainWindow : public QMainWindow
  10. {
  11. Q_OBJECT
  12. public:
  13. explicit MainWindow(QWidget *parent = 0);
  14. ~MainWindow();
  15. private slots:
  16. void on_pushButton_Connect_clicked(); //连接按钮槽函数
  17. void on_pushButton_Send_clicked(); //发送数据槽函数
  18. void socket_Read_Data(); //读数据槽函数
  19. void socket_Disconnected(); //断开连接槽函数
  20. private:
  21. Ui::MainWindow *ui;
  22. QTcpSocket *socket;
  23. };
  24. #endif // MAINWINDOW_H

mainwindow.cpp文件

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

最终成品

Qt TCP/IP网络通讯 - 图3

服务端

服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:
  1. 创建QTcpSever对象
  1. server = new QTcpServer();
  1. 侦听一个端口,使得客户端可以使用这个端口访问服务器
  1. server->listen(QHostAddress::Any, port);
  1. 当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问
  1. connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
  2. void MainWindow::server_New_Connect()
  3. {
  4. //获取客户端连接
  5. socket = server->nextPendingConnection();
  6. }
  1. 使用socket的write函数向客户端发送数据
  1. socket->write(data);
  1. 当socket接收缓冲区有新数据到来时,会发出readyRead()信号,因此为该信号添加槽函数以读取数据
  1. QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
  2. void MainWindow::socket_Read_Data()
  3. {
  4. QByteArray buffer;
  5. //读取缓冲区数据
  6. buffer = socket->readAll();
  7. }
  1. 取消侦听
  1. server->close();

mainwindow.h文件

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

mainwindow.cpp文件

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