• hwk5:QT中TCP客户端服务器实现


    一、TcpSer

    widget.h:

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. QT_BEGIN_NAMESPACE
    10. namespace Ui { class Widget; }
    11. QT_END_NAMESPACE
    12. class Widget : public QWidget
    13. {
    14. Q_OBJECT
    15. public:
    16. Widget(QWidget *parent = nullptr);
    17. ~Widget();
    18. private slots:
    19. void newConnection_slot(); //自定义处理newConnection信号的槽函数声明
    20. void readyRead_slot(); //自定义处理readyRead信号的槽函数声明
    21. void on_startBtn_clicked();
    22. private:
    23. Ui::Widget *ui;
    24. //定义服务器指针
    25. QTcpServer *server;
    26. //定义客户端容器
    27. QListclientList;
    28. };
    29. #endif // WIDGET_H

    widget.cpp:

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //实例化一个服务器
    9. server = new QTcpServer(this);
    10. connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
    11. }
    12. Widget::~Widget()
    13. {
    14. delete ui;
    15. }
    16. void Widget::on_startBtn_clicked()
    17. {
    18. quint16 port = ui->portEdit->text().toUInt();
    19. if(!server->listen(QHostAddress::Any,port))
    20. {
    21. QMessageBox::information(this,"失败","监听失败");
    22. return;
    23. }else{
    24. QMessageBox::information(this,"成功","服务器启动成功");
    25. }
    26. }
    27. void Widget::newConnection_slot()
    28. {
    29. qDebug()<<"有新的客户端发来连接请求";
    30. //记录连接过来的客户端套接字地址
    31. QTcpSocket *s=server->nextPendingConnection();
    32. //将该套接字放入客户端链表中
    33. clientList.push_back(s);
    34. //客户端发来数据,套接字会自动发射一个readyRead信号,可以连接到对应槽函数进行处理
    35. connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
    36. }
    37. void Widget::readyRead_slot()
    38. {
    39. qDebug()<<"有新的客户端消息发来了";
    40. //遍历客户端链表,将无效客户端移除
    41. for(int i=0;i<clientList.size();i++)
    42. {
    43. //如果返回值为0则表示该套接字为无效连接
    44. if(clientList[i]->state() == 0)
    45. {
    46. clientList.removeAt(i);
    47. }
    48. }
    49. //遍历客户端链表,判断是拿个客户端发来的数据
    50. for(int i=0;i<clientList.size();i++)
    51. {
    52. //返回值是待读数据的字节数,如果是0表示无数据待读
    53. if(clientList[i]->bytesAvailable()!=0)
    54. {
    55. //将该套接字中的数据读出来
    56. QByteArray msg = clientList[i]->readAll();
    57. //将数据展示到ui界面
    58. ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
    59. for(int j=0;j<clientList.size();j++)
    60. {
    61. clientList[j]->write(msg);
    62. }
    63. }
    64. }
    65. }

    main.cpp:

    1. #include "widget.h"
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication a(argc, argv);
    6. Widget w;
    7. w.show();
    8. return a.exec();
    9. }

    二、TcpCli

    widget.h:

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. QT_BEGIN_NAMESPACE
    7. namespace Ui { class Widget; }
    8. QT_END_NAMESPACE
    9. class Widget : public QWidget
    10. {
    11. Q_OBJECT
    12. public:
    13. Widget(QWidget *parent = nullptr);
    14. ~Widget();
    15. private slots:
    16. void on_sendBtn_clicked();
    17. void on_connectBtn_clicked();
    18. void on_disconnectBtn_clicked();
    19. void connected_slot(); //自定义处理connected信号的槽函数声明
    20. void readyRead_slot(); //自定义处理readyRead信号的槽函数声明
    21. void disconnected_slot(); //自定义处理disconnected信号的槽函数声明
    22. private:
    23. Ui::Widget *ui;
    24. //定义客户端指针
    25. QTcpSocket *socket;
    26. //定义字符串接收用户
    27. QString userName;
    28. };
    29. #endif // WIDGET_H

    widget.cpp:

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //给客户端实例化对象
    9. socket = new QTcpSocket(this);
    10. //如果客户端成功连接到服务器,客户端会发送一个connected信号,可以连接槽函数进行处理
    11. connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);
    12. //如果服务器发来信号,客户端会自动发送一个readyRead信号,连接到对应槽函数进行处理
    13. connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
    14. //如果客户端与服务器断开连接,客户端会自动发送一个disconnected信号,连接到槽函数进行处理
    15. connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
    16. }
    17. Widget::~Widget()
    18. {
    19. delete ui;
    20. }
    21. //连接服务器按钮对应的槽函数的定义
    22. void Widget::on_sendBtn_clicked()
    23. {
    24. //获取ui界面输入的内容
    25. QString msg =userName+ ": " + ui->msgEdit->text();
    26. //发送给服务器
    27. socket->write(msg.toLocal8Bit());
    28. //清空编辑框内容
    29. ui->msgEdit->clear();
    30. }
    31. //处理connected信号的槽函数的定义
    32. void Widget::on_connectBtn_clicked()
    33. {
    34. //获得ui界面上的信息
    35. userName = ui->userNameEdit->text();
    36. QString ip = ui->ipEdit->text();
    37. quint16 port = ui->portEdit->text().toUInt();
    38. //客户端调用connectToHost连接给定的服务器
    39. socket->connectToHost(ip,port);
    40. //因为只需要连接一次,所以将连接写到构造函数中去
    41. }
    42. //处理readyRead信号的槽函数的定义
    43. void Widget::on_disconnectBtn_clicked()
    44. {
    45. QString msg = userName +": 离开聊天室";
    46. socket->write(msg.toLocal8Bit());
    47. //断开连接
    48. //函数原型: virtual void disconnectFromHost();
    49. socket->disconnectFromHost();
    50. }
    51. void Widget::connected_slot()
    52. {
    53. QMessageBox::information(this,"成功","已成功进入聊天室");
    54. //向服务器发送一条数据:userName进入聊天室
    55. QString msg = userName + ":进入聊天室";
    56. socket->write(msg.toLocal8Bit()); //将数据写给服务器
    57. }
    58. void Widget::readyRead_slot()
    59. {
    60. //读取套接字中的信息
    61. QByteArray msg = socket->readAll();
    62. //将数据展示到ui界面
    63. ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
    64. }
    65. void Widget::disconnected_slot()
    66. {
    67. QMessageBox::information(this, "提示", "退出成功");
    68. }

    main.cpp:

    1. #include "widget.h"
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication a(argc, argv);
    6. Widget w;
    7. w.show();
    8. return a.exec();
    9. }

  • 相关阅读:
    Stable DIffusion系统教程 | 局部重绘,增删修改的魔法棒
    Wireshark新手小白基础使用方法
    MongoDB聚合运算符:$avg
    redis的详细介绍与操作命令
    [附源码]java毕业设计校园快递管理系统
    [ C++ ] 多态原理 多态(2)
    【Java】一只小菜坤的编程题之旅【4】
    BLE广播事件包解析&空口事例
    PolarDB-X 源码解读系列:DML 之 INSERT IGNORE 流程
    Web前端——立体相册的制作
  • 原文地址:https://blog.csdn.net/wxmchong/article/details/133561885