云计算百科
云计算领域专业知识百科平台

【Qt网络编程】Tcp多线程并发服务器和客户端通信

目录

一、编写思路

1、服务器

(1)总体思路widget.c(主线程)

(2)详细流程widget.c(主线程)

(1)总体思路chat_thread.c(处理聊天逻辑线程)

(2)详细流程chat_thread.h(处理聊天逻辑线程)

2、客户端

(1)总体思路widget.c(主线程)

(2)详细思路widget.c(主线程)

(1)总体思路chat_thread.c(处理聊天逻辑线程)

(2)详细流程chat_thread.c(处理聊天逻辑线程)

二、实现效果

1、服务器

2、客户端


完整代码请到指定链接下载:Qt网络编程-Tcp多线程并发服务器和客户端通信: 【Qt网络编程】Tcp多线程并发服务器和客户端通信

一、编写思路

1、服务器

(1)总体思路widget.c(主线程)

  • 初始化界面

    创建窗口、输入框、按钮等基本UI元素。

  • 创建服务器对象

    实现 My_tcp_server 并监听客户端连接。

  • 处理新客户端连接

    当有新客户端连接时,创建新的 Chat_thread 线程来处理通信。

  • 绑定信号槽

    确保主线程与客户端处理线程间的信号槽连接,使用 Qt::QueuedConnection 处理跨线程通信。

  • 处理消息传递

    接收和发送消息,并在界面上更新显示。

  • 服务器启动与关闭

    通过按钮控制服务器的启动和关闭,管理所有客户端线程的安全退出。

  • (2)详细流程widget.c(主线程)

  • 创建 Qt 界面及设置窗口属性: 首先通过 ui->setupUi(this); 来初始化用户界面,并设置窗口标题、大小等基本属性。这是 Qt 项目的常见步骤,通过 .ui 文件生成的类进行界面管理。

    Widget::Widget(QWidget *parent)
      : QWidget(parent)
      , ui(new Ui::Widget)  // 初始化UI对象
    {
       ui->setupUi(this);  // 设置UI界面
       this->setWindowTitle(\”–服务器–\”);  // 设置窗口标题
       this->resize(1024, 960);  // 设置窗口大小

       ui->le_ip->setText(\”127.0.0.1\”);
       ui->le_port->setText(\”9999\”);
    }

  • 初始化服务器对象 My_tcp_server 并处理客户端连接:

    • 创建 tcp_server 对象以处理客户端的连接。

    • 使用 connect 函数连接 tcp_server 的 new_descriptor 信号和匿名槽函数,确保一旦有新客户端连接,便创建一个 Chat_thread 来处理该客户端。

    this->tcp_server = new My_tcp_server(this);

    connect(tcp_server, &My_tcp_server::new_descriptor, this, [=](qintptr socketDescriptor){
       QMessageBox::information(this, \”提示\”, \”新的客户端连接!\”, QMessageBox::Ok, QMessageBox::Information);

       ui->btn_send->setEnabled(true);  // 启用“发送消息”按钮

       // 创建新线程处理客户端
       Chat_thread *chat_thread = new Chat_thread(socketDescriptor);
       chat_thread->moveToThread(chat_thread);  // 将线程和对象绑定到同一线程,防止冲突

       thread_list.append(chat_thread);
       
       // 启动线程处理客户端通信
       chat_thread->start();
    });

  • 管理客户端线程 Chat_thread:

    • 每当有新客户端连接时,创建一个 Chat_thread 并启动它处理客户端通信。通过 moveToThread 将 Chat_thread 的执行线程与该对象保持一致,避免跨线程冲突。

    • 使用 connect 绑定线程中的信号(如连接断开、接收消息)和主界面槽函数,确保客户端状态能够正确显示。

    Chat_thread *chat_thread = new Chat_thread(socketDescriptor);
    chat_thread->moveToThread(chat_thread);  // 将线程与对象绑定在同一线程

    thread_list.append(chat_thread);

    // 连接信号和槽
    connect(chat_thread, &Chat_thread::break_connect, this, [=](){
       ui->te_receive->append(currentTime + \”\\n【状态】客户端断开连接…\”);
       ui->btn_send->setEnabled(false);  // 禁用“发送消息”按钮
    });

    connect(chat_thread, &Chat_thread::recv_info, this, [=](QString data){
       currentTime = QDateTime::currentDateTime().toString(\”yyyy-MM-dd hh:mm:ss\”);
       ui->te_receive->append(currentTime + \”form client\\n   【数据】 \” + data);  // 在文本框中显示消息
    });

    chat_thread->start();  // 启动线程

  • 处理启动和关闭服务器的按钮事件:

    • on_btn_connect_clicked() 处理连接按钮点击事件,启动或关闭服务器。

    • 启动时,检查 IP 地址和端口的有效性,成功后开始监听客户端连接。

    • 关闭服务器时,停止监听,并确保所有已连接客户端线程安全退出。

    void Widget::on_btn_connect_clicked()
    {
       if (!is_server_running)
      {
           // 启动服务器
           QString ip_address = ui->le_ip->text().trimmed();
           QString port_text = ui->le_port->text().trimmed();
           
           if (!tcp_server->listen(QHostAddress(ip_address), port_text.toUInt()))
          {
               QMessageBox::warning(this, \”warning\”, \”服务器监听失败\”);
               return;
          }
           
           is_server_running = true;
           ui->btn_connect->setText(\”关闭服务器\”);
           ui->te_receive->append(currentTime + \”\\n【状态】服务器开始监听…\”);
      }
       else
      {
           // 停止服务器并关闭所有客户端线程
           tcp_server->close();
           for (Chat_thread *thread : qAsConst(thread_list))
          {
               thread->exit();
               thread->wait();
               thread->deleteLater();
          }
           thread_list.clear();
           is_server_running = false;
           ui->btn_connect->setText(\”创建服务器\”);
                      ui->te_receive->append(currentTime + \”\\n【状态】服务器已停止监听…\”);
          }
      }

  • 处理发送消息按钮的点击事件:

    • 当点击“发送消息”按钮时,触发 send_request 信号,利用信号槽机制将输入的消息发送给客户端。需要确保主线程和子线程的信号槽通信是异步进行的(通过 Qt::QueuedConnection)。

    void Widget::on_btn_send_clicked()
    {
       QString data = ui->te_send->toPlainText().toUtf8();
       emit send_request(data);  // 发出 send_request 信号
    }</

  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【Qt网络编程】Tcp多线程并发服务器和客户端通信
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!