socket(二)使用QT实现简单连接
socket(二)使用QT实现简单连接
首先,为了让我们完成更好的观察,我们需要先绘制主机与从机的界面:
我们之所以能够实现连接,主要是因为IP与端口为我们指引了他们的地址,所以我们才能精确的连接上。所以我们绘制这两个界面的时候,需要绘制输入IP与端口的输入框;由于我们需要通过socket去完成收发信息的工作,所以我们自然需要在这两个界面绘制接收区与输入区,绘制发送按钮;由于多个从机可以连接上主机,主机需要从多个从机中选择所需要的从机发送信息或者是向所有从机发送信息,所以我们需要一个下拉列表框,来选择我们需要发送信息的从机。


主机思路与代码
在QT中,有两个方便我们完成socket的头文件:
1 2 | #include <QTcpServer> #include <QTcpSocket> |
我们要使用他们,需要在.pro文件中添加
1 | QT += core gui network |
我们在界面中,对IP与端口的输入框进行转到槽操作,在函数中获取输入的IP与端口,端口为2-2^23次方,期间可以随意选择。
1 2 3 4 5 6 7 8 9 | void MainWindow::on_le_address_textChanged( const QString &arg) { ip = arg; } void MainWindow::on_le_port_textChanged( const QString &arg) { port = arg.toInt(); } |
当我们点击监听按钮,实现实现监听操作时,即创建一个新的TCP服务器对象,在指定的IP与端口上监听,如果监听成功,其IP与端口的输入框与其监听按钮都应失效,不可输入,不可点击,且设置一个信号槽去处理新链接。如果监听失败,则显示警告
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void MainWindow::on_pb_listen_clicked() { tcpServer = new QTcpServer(); if (tcpServer->listen(QHostAddress(ip),port)) { ui->le_port->setEnabled( false ); ui->le_address->setEnabled( false ); ui->pb_listen->setEnabled( false ); QObject::connect(tcpServer,SIGNAL(newConnection()), this ,SLOT(addClient())); } else { QMessageBox::warning( this , "waring" , "listen error" , QMessageBox::Close); } } |
当有新的客户端连接时被调用。首先从TCP服务器获取下一个待处理的连接,然后设置一个信号槽,当该连接有新数据可读时,将调用showMeassage()
函数。接着,它将新连接添加到list
列表中,并在一个下拉列表中添加一个新的项目来表示这个连接
1 2 3 4 5 6 7 8 | void MainWindow::addClient() { QTcpSocket* tcpSocket = tcpServer->nextPendingConnection(); connect(tcpSocket,SIGNAL(readyRead()), this ,SLOT(showMeassage())); list.append(tcpSocket); ui->cb_clientList->addItem( "tcpSocket" + QString::number(i)); i++; } |
如果我们需要查看是哪一个客户端发来的信息,则需要通过sender()函数进行确认,然后从socket读取数据显示在文本框中,为了分辨是哪个客户端发送过来的信息,所以我们在发送信息的前面添加该客户端的IP与端口,由于发送数据结束标志为“\r\n”,且人为在输入区输入无效,所以我们要在代码底层逻辑添加“\r\n”
1 2 3 4 5 6 7 8 9 | void MainWindow::showMeassage() { QTcpSocket* tcpSocket = (QTcpSocket*)sender(); QString ip = tcpSocket->peerAddress().toString(); qint16 port = tcpSocket->peerPort(); QString sender = ip + ":" + QString::number(port) + "-------->" + tcpSocket->readAll(); ui->tb_show->append(sender + "\r\n" ); } |
当主机需要发送信息时,如果需要向全体客户端发送信息,则选择广播,即下拉列表第一行,使用for循环向每一个客户端发送消息,如果只需要向其中一个客户端发送消息,则在下拉列表选择该项即可,当发送完消息后,清除发送区
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void MainWindow::on_pb_send_clicked() { QString message = ui->te_send->toPlainText(); if (ui->cb_clientList->currentIndex() == 0) { for ( int var = 0; var < list.size(); ++ var ) { QTcpSocket* tcpSocket = list[ var ]; tcpSocket->write(message.toUtf8()); } } else { QTcpSocket* tcpSocket = list[ui->cb_clientList->currentIndex() - 1]; tcpSocket->write(message.toUtf8()); } ui->te_send->clear(); } |
从机的代码与思路
与主机一样,添加头文件与.pro模块
然后,从机需要连接主机,所以从机需要在IP与端口的输入框中输入主机的IP与端口,然后通过转到槽获取
1 2 3 4 5 6 7 8 9 | void MainWindow::on_le_address_textChanged( const QString &arg) { ip = arg; } void MainWindow::on_le_port_textChanged( const QString &arg) { port = arg.toInt(); } |
输入IP与端口后,点击链接,创建新QTcpSocket对象,建立新TCP链接,当有新数据可读时,使用showMeassage()函数显示数据。当链接成功时,使用信号槽调用函数禁用界面元素,当链接断开时,使用信号槽调用函数启用界面元素
1 2 3 4 5 6 7 8 9 | void MainWindow::on_pb_connect_clicked() { tcpSocket = new QTcpSocket(); tcpSocket->connectToHost( "127.0.0.1" ,8888); connect(tcpSocket,SIGNAL(readyRead()), this ,SLOT(showMeassage())); connect(tcpSocket,SIGNAL(connected()), this ,SLOT(enableFalse())); connect(tcpSocket,SIGNAL(disconnected()), this ,SLOT(enableTrue())); } |
我们根据传入的布尔值来判断启用还是禁用元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void MainWindow::enableTrue() { enable( true ); } void MainWindow::enableFalse() { enable( false ); } void MainWindow::enable( bool flage) { ui->le_port->setEnabled(flage); ui->le_address->setEnabled(flage); ui->pb_connect->setEnabled(flage); } |
接收从主机发送过来的函数时,为了我们方便阅读,使用“\r\n”完成换行操作
1 2 3 4 | void MainWindow::showMeassage() { ui->tb_show->append(tcpSocket->readAll() + "\r\n" ); } |
当从机发送信息完成后,我们要清除发送区
1 2 3 4 5 6 | void MainWindow::on_pb_send_clicked() { QString message = ui->te_send->toPlainText(); tcpSocket->write(message.toUtf8()); ui->te_send->clear(); } |
运行效果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现