参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=56

说明:本文介绍Qt下实现tcp客户端和服务器通信的过程。

Linux下tcp客户端和服务器通信模型可参考我的另一篇博客:https://www.cnblogs.com/mrlayfolk/p/11968446.html。Qt下tcp通信的原理是一样的。

Qt的TCP通信模型如下:

(1)TCP服务器端

1)创建服务器套接字,使用QTcpServer()类;

2)将套接字设置为监听模式;

3)等待客户端连接请求,客户端连接上时会触发newConnection信号,可调用nextPendingConnection函数获取客户端的Socket信息;

4)和客户端进行通信,发送数据可使用write()函数,接收数据可使用read()或readAll函数()。

(2)TCP客户端

1)创建套接字;

2)连接服务器,使用connectToHost()函数;

3)和服务器进行通信,发送数据可使用write()函数,接收数据可使用read()或readAll函数()。

功能说明:分别创建两个窗口,一个用作TCP服务器端,一个用作TCP客户端,双方进行通信。窗口如下:

服务器窗口:                                                                             客户端窗口:

           

下面分别说明代码实现的步骤:

(1)服务器端

首先创建两个套接字指针。tcpserver用作服务器套接字,tcpsocket用作和客户端通信的通信套接字。

  1. 1 QTcpServer *tcpserver = NULL; //监听套接字
  2. 2 QTcpSocket *tcpsocket = NULL; //通信套接字

然后,创建套接字并启动监听。

  1. 1 //监听套接字,指定父对象,自动回收空间
  2. 2 tcpserver = new QTcpServer(this);
  3. 3 //启动监听
  4. 4 tcpserver->listen(QHostAddress::Any, 8888);

捕捉newConnect信号与槽函数,等待客户端连接:

  1. 1 //等待连接
  2. 2 connect(tcpserver, &QTcpServer::newConnection,
  3. 3 [=]() {
  4. 4 //取出建立好连接的套接字
  5. 5 tcpsocket = tcpserver->nextPendingConnection();
  6. 6 //获取对方的ip的端口
  7. 7 QString ip = tcpsocket->peerAddress().toString();
  8. 8 qint16 port = tcpsocket->peerPort();
  9. 9 QString tmp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
  10. 10 //在当前对话框显示谁和我连接了
  11. 11 ui->textEdit_recv->setText(tmp);
  12. 12 }
  13. 13 );

发送数据:

  1. 1 //获取编辑区内容
  2. 2 QString str = ui->textEdit_send->toPlainText();
  3. 3 //给对方发送数据
  4. 4 //QString -> char*
  5. 5 tcpsocket->write(str.toUtf8().data());

接收数据:

  1. 1 //接收数据
  2. 2 connect(tcpsocket, &QTcpSocket::readyRead,
  3. 3 [=](){
  4. 4 //从通信套接字中取出内容
  5. 5 QByteArray array = tcpsocket->readAll();
  6. 6 ui->textEdit_recv->append(array);
  7. 7 }
  8. 8 );

关闭连接:

  1. 1 //主动和客户端断开连接
  2. 2 tcpsocket->disconnectFromHost();
  3. 3 tcpsocket->close();
  4. 4 tcpsocket = NULL;

(2)客户端

客户端只需要创建一个套接字,用于和服务器建立连接并通信:

  1. 1 QTcpSocket *tcpsocket = NULL; //通信套接字
  2. 2 //分配空间,指定父对象
  3. 3 tcpsocket = new QTcpSocket(this);

和服务器端建立连接:

  1. 1 //获取服务器ip和端口
  2. 2 QString ip = ui->lineEdit_ip->text();
  3. 3 qint16 port = ui->lineEdit_port->text().toInt();
  4. 4 //主动和服务器建立连接
  5. 5 tcpsocket->connectToHost(QHostAddress(ip), port);

发送数据:

  1. 1 //获取编辑框内容
  2. 2 QString str = ui->textEdit_send->toPlainText();
  3. 3 //发送数据
  4. 4 tcpsocket->write(str.toUtf8().data());

接收数据:

  1. 1 connect(tcpsocket, &QTcpSocket::readyRead,
  2. 2 [=](){
  3. 3 //获取对方发送的内容
  4. 4 QByteArray array = tcpsocket->readAll();
  5. 5 //追加到编辑区中
  6. 6 ui->textEdit_recv->append(array);
  7. 7 }
  8. 8 );

断开连接:

  1. 1 //主动和对方断开连接
  2. 2 tcpsocket->disconnectFromHost();
  3. 3 tcpsocket->close();

(3)完整的工程代码:

工程所包含的文件有,serverwidget.cpp和serverwidget.h是服务器端的代码,clientwidget.cpp和clientwidget.h是客户端代码。

 serverwidget.cpp代码:

  1. 1 #include "serverwidget.h"
  2. 2 #include "ui_serverwidget.h"
  3. 3
  4. 4 ServerWidget::ServerWidget(QWidget *parent) :
  5. 5 QWidget(parent),
  6. 6 ui(new Ui::ServerWidget)
  7. 7 {
  8. 8 ui->setupUi(this);
  9. 9 setWindowTitle("服务器: 8888");
  10. 10
  11. 11 //监听套接字,指定父对象,自动回收空间
  12. 12 tcpserver = new QTcpServer(this);
  13. 13 //启动监听
  14. 14 tcpserver->listen(QHostAddress::Any, 8888);
  15. 15 //等待连接
  16. 16 connect(tcpserver, &QTcpServer::newConnection,
  17. 17 [=]() {
  18. 18 //取出建立好连接的套接字
  19. 19 tcpsocket = tcpserver->nextPendingConnection();
  20. 20 //获取对方的ip的端口
  21. 21 QString ip = tcpsocket->peerAddress().toString();
  22. 22 qint16 port = tcpsocket->peerPort();
  23. 23 QString tmp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
  24. 24 //在当前对话框显示谁和我连接了
  25. 25 ui->textEdit_recv->setText(tmp);
  26. 26
  27. 27 //接收数据
  28. 28 connect(tcpsocket, &QTcpSocket::readyRead,
  29. 29 [=](){
  30. 30 //从通信套接字中取出内容
  31. 31 QByteArray array = tcpsocket->readAll();
  32. 32 ui->textEdit_recv->append(array);
  33. 33 }
  34. 34 );
  35. 35 }
  36. 36 );
  37. 37 }
  38. 38
  39. 39 ServerWidget::~ServerWidget()
  40. 40 {
  41. 41 delete ui;
  42. 42 }
  43. 43
  44. 44
  45. 45 void ServerWidget::on_pushButton_close_clicked()
  46. 46 {
  47. 47 if (NULL == tcpsocket) {
  48. 48 return;
  49. 49 }
  50. 50 //主动和客户端断开连接
  51. 51 tcpsocket->disconnectFromHost();
  52. 52 tcpsocket->close();
  53. 53 tcpsocket = NULL;
  54. 54 }
  55. 55
  56. 56 void ServerWidget::on_pushButton_send_clicked()
  57. 57 {
  58. 58 if (NULL == tcpsocket) {
  59. 59 return;
  60. 60 }
  61. 61 //获取编辑区内容
  62. 62 QString str = ui->textEdit_send->toPlainText();
  63. 63 //给对方发送数据
  64. 64 //QString -> char*
  65. 65 tcpsocket->write(str.toUtf8().data());
  66. 66 }

View Code

 serverwidget.h代码:

  1. 1 #ifndef SERVERWIDGET_H
  2. 2 #define SERVERWIDGET_H
  3. 3
  4. 4 #include <QWidget>
  5. 5 #include <QTcpServer> //监听套接字
  6. 6 #include <QTcpSocket> //通信套接字
  7. 7
  8. 8 namespace Ui {
  9. 9 class ServerWidget;
  10. 10 }
  11. 11
  12. 12 class ServerWidget : public QWidget
  13. 13 {
  14. 14 Q_OBJECT
  15. 15
  16. 16 public:
  17. 17 explicit ServerWidget(QWidget *parent = 0);
  18. 18 ~ServerWidget();
  19. 19
  20. 20 private slots:
  21. 21 void on_pushButton_send_clicked();
  22. 22
  23. 23 void on_pushButton_close_clicked();
  24. 24
  25. 25 private:
  26. 26 Ui::ServerWidget *ui;
  27. 27 QTcpServer *tcpserver = NULL; //监听套接字
  28. 28 QTcpSocket *tcpsocket = NULL; //通信套接字
  29. 29 };
  30. 30
  31. 31 #endif // SERVERWIDGET_H

View Code

clientwidget.cpp代码:

  1. 1 #include "clientwidget.h"
  2. 2 #include "ui_clientwidget.h"
  3. 3 #include <QHostAddress>
  4. 4
  5. 5 clientwidget::clientwidget(QWidget *parent) :
  6. 6 QWidget(parent),
  7. 7 ui(new Ui::clientwidget)
  8. 8 {
  9. 9 ui->setupUi(this);
  10. 10 setWindowTitle("客户端");
  11. 11 //分配空间,指定父对象
  12. 12 tcpsocket = new QTcpSocket(this);
  13. 13 //建立连接
  14. 14 connect(tcpsocket, &QTcpSocket::connected,
  15. 15 [=]() {
  16. 16 ui->textEdit_recv->setText("成功和服务器建立了连接");
  17. 17 }
  18. 18 );
  19. 19 //接收数据
  20. 20 connect(tcpsocket, &QTcpSocket::readyRead,
  21. 21 [=](){
  22. 22 //获取对方发送的内容
  23. 23 QByteArray array = tcpsocket->readAll();
  24. 24 //追加到编辑区中
  25. 25 ui->textEdit_recv->append(array);
  26. 26 }
  27. 27 );
  28. 28 //断开连接
  29. 29 connect(tcpsocket, &QTcpSocket::disconnected,
  30. 30 [=](){
  31. 31 ui->textEdit_recv->append("和服务器断开了连接");
  32. 32 }
  33. 33 );
  34. 34 }
  35. 35
  36. 36 clientwidget::~clientwidget()
  37. 37 {
  38. 38 delete ui;
  39. 39 }
  40. 40
  41. 41 void clientwidget::on_pushButton_send_clicked()
  42. 42 {
  43. 43 //获取编辑框内容
  44. 44 QString str = ui->textEdit_send->toPlainText();
  45. 45 //发送数据
  46. 46 tcpsocket->write(str.toUtf8().data());
  47. 47 }
  48. 48
  49. 49 void clientwidget::on_pushButton_close_clicked()
  50. 50 {
  51. 51 //主动和对方断开连接
  52. 52 tcpsocket->disconnectFromHost();
  53. 53 tcpsocket->close();
  54. 54 }
  55. 55
  56. 56 void clientwidget::on_pushButton_connect_clicked()
  57. 57 {
  58. 58 //获取服务器ip和端口
  59. 59 QString ip = ui->lineEdit_ip->text();
  60. 60 qint16 port = ui->lineEdit_port->text().toInt();
  61. 61 //主动和服务器建立连接
  62. 62 tcpsocket->connectToHost(QHostAddress(ip), port);
  63. 63 }

View Code

clientwidget.h代码:

  1. 1 #ifndef CLIENTWIDGET_H
  2. 2 #define CLIENTWIDGET_H
  3. 3
  4. 4 #include <QWidget>
  5. 5 #include <QTcpSocket>
  6. 6
  7. 7 namespace Ui {
  8. 8 class clientwidget;
  9. 9 }
  10. 10
  11. 11 class clientwidget : public QWidget
  12. 12 {
  13. 13 Q_OBJECT
  14. 14
  15. 15 public:
  16. 16 explicit clientwidget(QWidget *parent = 0);
  17. 17 ~clientwidget();
  18. 18
  19. 19 private slots:
  20. 20 void on_pushButton_send_clicked();
  21. 21
  22. 22 void on_pushButton_close_clicked();
  23. 23
  24. 24 void on_pushButton_connect_clicked();
  25. 25
  26. 26 private:
  27. 27 Ui::clientwidget *ui;
  28. 28 QTcpSocket *tcpsocket = NULL;
  29. 29 };
  30. 30
  31. 31 #endif // CLIENTWIDGET_H

View Code

main.cpp代码,启动两个窗口:

  1. 1 #include "serverwidget.h"
  2. 2 #include <QApplication>
  3. 3 #include "clientwidget.h"
  4. 4
  5. 5 int main(int argc, char *argv[])
  6. 6 {
  7. 7 QApplication a(argc, argv);
  8. 8 ServerWidget w;
  9. 9 clientwidget w2;
  10. 10 w.show();
  11. 11 w2.show();
  12. 12
  13. 13 return a.exec();
  14. 14 }

View Code

运行进行测试:

 

版权声明:本文为mrlayfolk原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mrlayfolk/p/13283517.html