QTTCP客户端服务端通信

news/2024/10/18 2:39:50/

目录

网络模块介绍

TCP介绍

 TCP 服务端应用实例

 TCP 客户端应用实例

运行结果:

网络模块介绍

Qt 网络模块为我们提供了编写 TCP / IP 客户端和服务器的类。它提供了较低级别的类,例
如代表低级网络概念的 QTcpSocket QTcpServer QUdpSocket ,以及诸如 QNetworkRequest
QNetworkReply QNetworkAccessManager 之类的高级类来执行使用通用协议的网络操作。
还提供了诸如 QNetworkConfiguration QNetworkConfigurationManager QNetworkSession 等类,
实现承载管理。
想要在程序中使用 Qt 网络模块,我们需要在 pro 项目配置文件里增加下面的一条语句。
QT += network

TCP介绍

TCP 协议( Transmission Control Protocol )全称是传输控制协议是一种 面向连接的、可靠的、
基于字节流 的传输层通信协议。
TCP 通信必 须先建立 TCP 连接 ,通信端分为客户端和服务端。服务端通过监听某个端口
来监听是否有客户端连接到来,如果有连接到来,则建立新的 socket 连接;客户端通过 ip
port 连接服务端,当成功建立连接之后,就可进行数据的收发了。需要注意的是,在 Qt 中,
Qt socket 当成输入输出流来对待的,数据的收发是通过 read() write() 来进行的,需要与我
们常见的 send() recv() 进行区分。
TCP 客户端与服务端通信示意图如下。

 TCP 服务端应用实例

本例大体流程
首先获取本地 IP 地址。创建一个 tcpSocket 套接字,一个 tcpServer 服务端。点击监听即监听本
地的主机 IP 地址和端口,同时等待服务端的连接。此程序需要结合客户端一起使用,可实现多个客户端的传播。
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QNetworkInterface>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;/* tcp 服务器 */QTcpServer *tcpServer;/* 通信套接字 */QTcpSocket *tcpSocket;/* 存储本地的 ip 列表地址 */QList<QHostAddress> IPlist;/* 获取本地的所有 ip */void getLocalHostIP();private slots:/* 客户端连接处理槽函数 */void clientConnected();/* 开始监听槽函数 */void startListen();/* 停止监听槽函数 */void stopListen();/* 清除文本框时的内容 */void clearTextBrowser();/* 接收到消息 */void receiveMessages();/* 发送消息 */void sendMessages();/* 连接状态改变槽函数 */void socketStateChange(QAbstractSocket::SocketState);};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);tcpServer = new QTcpServer(this);tcpSocket = new QTcpSocket(this);ui->spinBox->setRange(10000, 99999);ui->pushButton_5->setEnabled(false);getLocalHostIP();/* 信号槽连接 */connect(ui->pushButton, SIGNAL(clicked()),this, SLOT(startListen()));connect(ui->pushButton_5, SIGNAL(clicked()),this, SLOT(stopListen()));connect(ui->pushButton_6, SIGNAL(clicked()),this, SLOT(clearTextBrowser()));connect(ui->pushButton_4, SIGNAL(clicked()),this, SLOT(sendMessages()));connect(tcpServer, SIGNAL(newConnection()),this, SLOT(clientConnected()));
}Widget::~Widget()
{delete ui;
}
/* 新的客户端连接 */
void Widget::clientConnected()
{/* 获取客户端的套接字 */tcpSocket = tcpServer->nextPendingConnection();/* 客户端的 ip 信息 */QString ip = tcpSocket->peerAddress().toString();/* 客户端的端口信息 */quint16 port = tcpSocket->peerPort();/* 在文本浏览框里显示出客户端的连接信息 */ui->textBrowser->append("客户端已连接");ui->textBrowser->append("客户端 ip 地址:" + ip);ui->textBrowser->append("客户端端口:" + QString::number(port));connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(receiveMessages()));connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(socketStateChange(QAbstractSocket::SocketState)));
}
void Widget::getLocalHostIP()
{QList<QNetworkInterface> list= QNetworkInterface::allInterfaces();/* 遍历 list */foreach (QNetworkInterface interface, list) {/* QNetworkAddressEntry 类存储 IP 地址子网掩码和广播地址 */QList<QNetworkAddressEntry> entryList= interface.addressEntries();/* 遍历 entryList */foreach (QNetworkAddressEntry entry, entryList) {/* 过滤 IPv6 地址,只留下 IPv4 */if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {ui->comboBox->addItem(entry.ip().toString());/* 添加到 IP 列表中 */IPlist<<entry.ip();}}}
}
/* 开始监听槽函数 */
void Widget::startListen()
{/* 需要判断当前主机是否有IP项 */if (ui->comboBox->currentIndex() != -1) {qDebug()<<"start listen"<<endl;tcpServer->listen(IPlist[ui->comboBox->currentIndex()],ui->spinBox->value());/* 设置按钮与下拉列表框的状态 */ui->pushButton->setEnabled(false);ui->pushButton_5->setEnabled(true);ui->comboBox->setEnabled(false);ui->spinBox->setEnabled(false);/* 在文本浏览框里显示出服务端 */ui->textBrowser->append("服务器IP地址:"+ ui->comboBox->currentText());ui->textBrowser->append("正在监听端口:"+ ui->spinBox->text());}
}
/* 停止监听槽函数 */
void Widget::stopListen()
{qDebug()<<"stop listen"<<endl;/* 停止监听 */tcpServer->close();/* 如果是连接上了也应该断开,如果不断开客户端还能继续发送信息,* 因为socket未断开,还在监听上一次端口 */if (tcpSocket->state() == tcpSocket->ConnectedState)tcpSocket->disconnectFromHost();/* 设置按钮与下拉列表框的状态  */ui->pushButton_5->setEnabled(false);ui->pushButton->setEnabled(true);ui->comboBox->setEnabled(true);ui->spinBox->setEnabled(true);/* 将停止监听的信息添加到文本浏览框中 */ui->textBrowser->append("已停止监听端口:" + ui->spinBox->text());
}
/* 清除文本框时的内容 */
void Widget::clearTextBrowser()
{/* 清除文本浏览器的内容 */ui->textBrowser->clear();
}/* 接收到消息 */
void Widget::receiveMessages()
{/* 读取接收到的消息 */QString messages = "客户端:" + tcpSocket->readAll();ui->textBrowser->append(messages);
}
/* 发送消息 */
void Widget::sendMessages()
{QList <QTcpSocket *> socketList=tcpServer->findChildren<QTcpSocket *>();qDebug()<<"tcpSocket 数量: "<<socketList.count()<<endl;if(socketList.count()== 0){ui->textBrowser->append("请先与客户端连接!");return;}foreach(QTcpSocket *tmpTcpSocket,socketList){tmpTcpSocket->write(ui->lineEdit->text().toUtf8());}ui->textBrowser->append("服务端 "+ui->lineEdit->text());
}
/* 连接状态改变槽函数 */
void Widget::socketStateChange(QAbstractSocket::SocketState state)
{switch (state) {case QAbstractSocket::UnconnectedState:ui->textBrowser->append("scoket状态:客户端断开连接");tcpSocket->deleteLater();break;case QAbstractSocket::ConnectedState:ui->textBrowser->append("scoket状态:客户端已连接");break;case QAbstractSocket::ConnectingState:ui->textBrowser->append("scoket状态:ConnectingState");break;case QAbstractSocket::HostLookupState:ui->textBrowser->append("scoket状态:HostLookupState");break;case QAbstractSocket::ClosingState:ui->textBrowser->append("scoket状态:ClosingState");break;case QAbstractSocket::ListeningState:ui->textBrowser->append("scoket状态:ListeningState");break;case QAbstractSocket::BoundState:ui->textBrowser->append("scoket状态:BoundState");break;default:break;}
}

 TCP 客户端应用实例

本例大体流程:
首先获取本地 IP 地址。创建一个 tcpSocket 套接字,然后用 tcpSocket 套接字使用 connectToHost 函数连接服务端的主机 IP 地址和端口,即可相互通信。

 widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QNetworkInterface>
#include <QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;/* 通信套接字 */QTcpSocket *tcpSocket;/* 存储本地的ip列表地址 */QList<QHostAddress> IPlist;/* 获取本地的所有ip */void getLocalHostIP();
private slots:/* 连接 */void toConnect();/* 断开连接 */void toDisConnect();/* 已连接 */void connected();/* 已断开连接 */void disconnected();/* 清除文本框时的内容 */void clearTextBrowser();/* 接收到消息 */void receiveMessages();/* 发送消息 */void sendMessages();/* 连接状态改变槽函数 */void socketStateChange(QAbstractSocket::SocketState);
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);/* tcp套接字 */tcpSocket = new QTcpSocket(this);/* 设置端口号的范围,注意不要与主机的已使用的端口号冲突 */ui->spinBox->setRange(10000, 99999);/* 设置断开连接状态不可用 */ui->pushButton_2->setEnabled(false);/* 获取本地 ip */getLocalHostIP();/* 信号槽连接 */connect(ui->pushButton, SIGNAL(clicked()),this, SLOT(toConnect()));connect(ui->pushButton_2, SIGNAL(clicked()),this, SLOT(toDisConnect()));connect(ui->pushButton_3, SIGNAL(clicked()),this, SLOT(clearTextBrowser()));connect(ui->pushButton_4, SIGNAL(clicked()),this, SLOT(sendMessages()));connect(tcpSocket, SIGNAL(connected()),this, SLOT(connected()));connect(tcpSocket, SIGNAL(disconnected()),this, SLOT(disconnected()));connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(receiveMessages()));connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(socketStateChange(QAbstractSocket::SocketState)));
}Widget::~Widget()
{delete ui;
}
void Widget::toConnect()
{/* 如果连接状态还没有连接 */if (tcpSocket->state() != tcpSocket->ConnectedState) {/* 指定IP地址和端口连接 */tcpSocket->connectToHost(IPlist[ui->comboBox->currentIndex()],ui->spinBox->value());}
}void Widget::toDisConnect()
{/* 断开连接 */tcpSocket->disconnectFromHost();/* 关闭socket*/tcpSocket->close();
}void Widget::connected()
{/* 显示已经连接 */ui->textBrowser->append("已经连上服务端");/* 设置按钮与下拉列表框的状态 */ui->pushButton->setEnabled(false);ui->pushButton_2->setEnabled(true);ui->comboBox->setEnabled(false);ui->spinBox->setEnabled(false);
}void Widget::disconnected()
{/* 显示已经断开连接 */ui->textBrowser->append("已经断开服务端");/* 设置按钮与下拉列表框的状态  */ui->pushButton_2->setEnabled(false);ui->pushButton->setEnabled(true);ui->comboBox->setEnabled(true);ui->spinBox->setEnabled(true);
}/* 获取本地IP */
void Widget::getLocalHostIP()
{// /* 获取主机的名称 */// QString hostName = QHostInfo::localHostName();// /* 主机的信息 */// QHostInfo hostInfo = QHostInfo::fromName(hostName);// /* ip列表,addresses返回ip地址列表,注意主机应能从路由器获取到// * IP,否则可能返回空的列表(ubuntu用此方法只能获取到环回IP) */// IPlist = hostInfo.addresses();// qDebug()<<IPlist<<endl;// /* 遍历IPlist */// foreach (QHostAddress ip, IPlist) {//      if (ip.protocol() == QAbstractSocket::IPv4Protocol)//          comboBox->addItem(ip.toString());//    }/* 获取所有的网络接口,* QNetworkInterface类提供主机的IP地址和网络接口的列表 */QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();/* 遍历list */foreach (QNetworkInterface interface, list) {/* QNetworkAddressEntry类存储IP地址子网掩码和广播地址 */QList<QNetworkAddressEntry> entryList = interface.addressEntries();/* 遍历entryList */foreach (QNetworkAddressEntry entry, entryList) {/* 过滤IPv6地址,只留下IPv4 */if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {ui->comboBox->addItem(entry.ip().toString());/* 添加到IP列表中 */IPlist<<entry.ip();}}}
}/* 清除文本浏览框里的内容 */
void Widget::clearTextBrowser()
{/* 清除文本浏览器的内容 */ui->textBrowser->clear();
}/* 客户端接收消息 */
void Widget::receiveMessages()
{/* 读取接收到的消息 */QString messages = tcpSocket->readAll();ui->textBrowser->append("服务端:" + messages);
}/* 客户端发送消息 */
void Widget::sendMessages()
{if(NULL == tcpSocket)return;if(tcpSocket->state() == tcpSocket->ConnectedState) {/* 客户端显示发送的消息 */ui->textBrowser->append("客户端:" + ui->lineEdit->text());/* 发送消息 */tcpSocket->write(ui->lineEdit->text().toUtf8().data());}
}/* 客户端状态改变 */
void Widget::socketStateChange(QAbstractSocket::SocketState state)
{switch (state) {case QAbstractSocket::UnconnectedState:ui->textBrowser->append("scoket状态:与服务端未连接");tcpSocket->deleteLater();break;case QAbstractSocket::ConnectedState:ui->textBrowser->append("scoket状态:与服务端已连接");break;case QAbstractSocket::ConnectingState:ui->textBrowser->append("scoket状态:ConnectingState");break;case QAbstractSocket::HostLookupState:ui->textBrowser->append("scoket状态:HostLookupState");break;case QAbstractSocket::ClosingState:ui->textBrowser->append("scoket状态:ClosingState");break;case QAbstractSocket::ListeningState:ui->textBrowser->append("scoket状态:ListeningState");break;case QAbstractSocket::BoundState:ui->textBrowser->append("scoket状态:BoundState");break;default:break;}
}

运行结果:

 

 

 


http://www.ppmy.cn/news/735035.html

相关文章

广西柳州电信 华为HG8120C光猫超级密码

UserName"telecomadmin" Password"telecomadmin52401790"

求助华为HG8321R光猫这样还有救吗

刷机失败后&#xff0c;网线连不上&#xff0c;只有电源灯亮&#xff0c;用ttl线连上一直这样循环&#xff0c;无法输入命令行 华为HG8321R刷机失败

华为HG8204 光纤猫的路由设置

原来安装光纤猫时&#xff0c;因为卡在路由设置那里&#xff0c;搞了好长时间&#xff0c;参考了网上提供的步骤&#xff0c;感觉一个字——乱&#xff01;还是自己写一篇供大家参考。 光纤的速度一般的比双绞线的网速快&#xff0c;但是想要多个人使用&#xff0c;就要另外连…

破解电信光猫华为HG8120C关闭路由功能方法

昨天电信的工作人员来安装了电信的光纤宽带&#xff0c;使用的是华为HG8120C这款光电转换器与路由器一体机 这导致下级路由无法直接使用PPPOE拨号连接到互联网&#xff0c;且无法使用端口映射来实现外网访问 而华为开放给用户的useradmin这个账号基本就是给你看着玩的&#xff…

华为HG8240F光猫破解

家里光猫被联通改了管理员的密码&#xff0c;尝试恢复出厂&#xff0c;但是只要注册上就被改&#xff0c;而且telnet什么的也都没有。没有管理员账号&#xff0c;IPTV等的vlan id也看不到&#xff0c;改完只能上网。 想了个办法&#xff0c;再找一个光猫&#xff0c;配置上网&…

华为hg8240光猫破解方法

要知道这台光猫的本质是一台迷你型的电脑&#xff0c;有自己的CPU&#xff0c;存储器之类 当然也有自己的系统&#xff0c;精简版的linux。 知道了这个接下来就好做了。 第一步把你的电脑用网线接到光猫的任意LAN口上。 点击开始菜单&#xff0c;在运行框中输入cmd 第二步&…

破解电信光猫华为HG8120C

昨天电信的工作人员来安装了电信的光纤宽带&#xff0c;使用的是华为HG8120C这款光电转换器与路由器一体机 这导致下级路由无法直接使用PPPOE拨号连接到互联网&#xff0c;且无法使用端口映射来实现外网访问 而华为开放给用户的useradmin这个账号基本就是给你看着玩的&#x…

SSM学习笔记-------MyBatis

MyBatis学习笔记 一、入门二、XML配置1、configuration&#xff08;配置&#xff09;2、properties&#xff08;属性&#xff09;3、settings&#xff08;设置&#xff09;4、typeAliases&#xff08;类型别名&#xff09;5、typeHandlers&#xff08;类型处理器&#xff09;6、…