Qt学习笔记-带TCP数据传输的局域网聊天软件
生活随笔
收集整理的這篇文章主要介紹了
Qt学习笔记-带TCP数据传输的局域网聊天软件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
程序運行截圖如下:
然后選擇一個文件,進行傳輸。
程序結構如下:
代碼如下:
tcpreceiver.h
#ifndef TCPRECEIVER_H #define TCPRECEIVER_H#include <QWidget> #include <QAbstractSocket> #include <QTcpServer> class QTcpSocket; class QFile;namespace Ui { class TcpReceiver; }class TcpReceiver : public QWidget {Q_OBJECTpublic:explicit TcpReceiver(const int port,QWidget *parent = 0);~TcpReceiver();public slots:void start();void acceptConnection();void updateServerProgress();void displayError(QAbstractSocket::SocketError socketError);void startBtnClicked();private:Ui::TcpReceiver *ui;QTcpServer m_tcpServer;QTcpSocket *m_tcpServerConnection;qint64 m_totalBytes;qint64 m_bytesReceived;qint64 m_fileNameSize;QString m_fileName;QFile *m_localFile;QByteArray m_inBlock;int m_port; };#endif // TCPRECEIVER_Htcpsender.h
#ifndef TCPSENDER_H #define TCPSENDER_H#include <QWidget> #include <QAbstractSocket> class QTcpSocket; class QFile;namespace Ui { class TcpSender; }class TcpSender : public QWidget {Q_OBJECTpublic:explicit TcpSender(const QString ip,const QString port,QWidget *parent = 0);~TcpSender();public slots:void openFile();void send();void startTransfer();void updateClientProgress(qint64);void displayError(QAbstractSocket::SocketError);void openBtnClicked();void sendBtnClicked();private:Ui::TcpSender *ui;QTcpSocket *m_tcpClient;QFile *m_localFile;qint64 m_totalBytes;qint64 m_bytesWritten;qint64 m_bytesToWrite;qint64 m_payloadSize;QString m_fileName;QByteArray m_outBlock; };#endif // TCPSENDER_Hwidget.h
#ifndef WIDGET_H #define WIDGET_H#include <QWidget>class QUdpSocket; class TcpSender; class TcpReceiver;namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();public slots:void dataReceived();void btnClicked();void widgetEnable(QString data);void setPortBtnClickd();void peerLineEditChange(QString data);void sendFileBtnClicked();private:Ui::Widget *ui;QUdpSocket *m_udpSocket;TcpSender *m_tcpSender;TcpReceiver *m_tcpReceiver;QString m_peerIp; };#endif // WIDGET_Hmain.cpp
#include "widget.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }tcpreceiver.cpp
#include "tcpreceiver.h" #include "ui_tcpreceiver.h"#include <QtNetwork> #include <QDebug>TcpReceiver::TcpReceiver(const int port, QWidget *parent) :QWidget(parent),ui(new Ui::TcpReceiver) {ui->setupUi(this);m_port=port;connect(&m_tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));connect(ui->startButton,SIGNAL(clicked(bool)),this,SLOT(startBtnClicked())); }void TcpReceiver::start(){if(!m_tcpServer.listen(QHostAddress::LocalHost,m_port)){qDebug()<<m_tcpServer.errorString();close();return;}ui->startButton->setEnabled(false);m_totalBytes=0;m_bytesReceived=0;m_fileNameSize=0;ui->serverStatusLabel->setText("監聽");ui->serverProgressBar->reset(); }void TcpReceiver::acceptConnection(){m_tcpServerConnection=m_tcpServer.nextPendingConnection();connect(m_tcpServerConnection,SIGNAL(readyRead()),this,SLOT(updateServerProgress()));connect(m_tcpServerConnection,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));ui->serverStatusLabel->setText("接受連接");//關閉服務器不再監聽,直接進入數據收發m_tcpServer.close(); }void TcpReceiver::updateServerProgress(){QDataStream in(m_tcpServerConnection);in.setVersion(QDataStream::Qt_5_7);// 如果接收到的數據小于16個字節,保存到來的文件頭結構if (m_bytesReceived<=sizeof(qint64)*2){if((m_tcpServerConnection->bytesAvailable()>=sizeof(qint64)*2)&&(m_fileNameSize==0)){// 接收數據總大小信息和文件名大小信息in>>m_totalBytes>>m_fileNameSize;m_bytesReceived +=sizeof(qint64)*2;}if((m_tcpServerConnection->bytesAvailable()>=m_fileNameSize)&&(m_fileNameSize!=0)){// 接收文件名,并建立文件in>>m_fileName;ui->serverStatusLabel->setText(tr("接收文件 %1 …").arg(m_fileName));m_bytesReceived+=m_fileNameSize;m_localFile = new QFile(m_fileName);if (!m_localFile->open(QFile::WriteOnly)){qDebug() << "server: open file error!";return;}}else{return;}}// 如果接收的數據小于總數據,那么寫入文件if(m_bytesReceived<m_totalBytes) {m_bytesReceived+=m_tcpServerConnection->bytesAvailable();m_inBlock = m_tcpServerConnection->readAll();m_localFile->write(m_inBlock);m_inBlock.resize(0);}ui->serverProgressBar->setMaximum(m_totalBytes);ui->serverProgressBar->setValue(m_bytesReceived);// 接收數據完成時if (m_bytesReceived==m_totalBytes){m_tcpServerConnection->close();m_localFile->close();ui->startButton->setEnabled(true);ui->serverStatusLabel->setText(tr("接收文件 %1 成功!").arg(m_fileName));} }void TcpReceiver::displayError(QAbstractSocket::SocketError socketError){Q_UNUSED(socketError)qDebug()<<m_tcpServerConnection->errorString();m_tcpServerConnection->close();ui->serverProgressBar->reset();ui->serverStatusLabel->setText("服務端就緒");ui->startButton->setEnabled(true); }void TcpReceiver::startBtnClicked(){start(); }TcpReceiver::~TcpReceiver() {delete ui; }tcpsender.cpp
#include "tcpsender.h" #include "ui_tcpsender.h"#include <QtNetwork> #include <QFileDialog>TcpSender::TcpSender(const QString ip, const QString port, QWidget *parent) :QWidget(parent),ui(new Ui::TcpSender) {ui->setupUi(this);ui->hostLineEdit->setText(ip);ui->portLineEdit->setText(port);ui->hostLineEdit->setEnabled(false);ui->portLineEdit->setEnabled(false);m_payloadSize=64*1024;m_totalBytes=0;m_bytesWritten=0;m_bytesToWrite=0;m_tcpClient=new QTcpSocket(this);connect(m_tcpClient,SIGNAL(connected()),this,SLOT(startTransfer()));connect(m_tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64)));connect(m_tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));connect(ui->sendButton,SIGNAL(clicked(bool)),this,SLOT(sendBtnClicked()));connect(ui->openButton,SIGNAL(clicked(bool)),this,SLOT(openBtnClicked())); }void TcpSender::openFile(){m_fileName=QFileDialog::getOpenFileName(this);if(!m_fileName.isEmpty()){ui->sendButton->setEnabled(true);ui->clientStatusLabel->setText(QString("打開文件 %1 成功!").arg(m_fileName));} }void TcpSender::send(){ui->sendButton->setEnabled(false);m_bytesWritten=0;ui->clientStatusLabel->setText("連接中...");m_tcpClient->connectToHost(ui->hostLineEdit->text(),ui->portLineEdit->text().toInt()); }void TcpSender::startTransfer(){m_localFile=new QFile(m_fileName);if(!m_localFile->open(QFile::ReadOnly)){qDebug()<<"client:open file error!";return;}m_totalBytes=m_localFile->size();QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_5_7);QString currentFileName=m_fileName.right(m_fileName.size()-m_fileName.lastIndexOf('/')-1);//文件總大小、文件名大小、文件名sendOut<<qint64(0)<<qint64(0)<<currentFileName;m_totalBytes+=m_outBlock.size();sendOut.device()->seek(0);sendOut<<m_totalBytes<<qint64(m_outBlock.size()-sizeof(qint64)*2);m_bytesToWrite=m_totalBytes-m_tcpClient->write(m_outBlock);ui->clientStatusLabel->setText("已連接");m_outBlock.resize(0); }void TcpSender::updateClientProgress(qint64 numBytes){m_bytesWritten+=(int)numBytes;if(m_bytesToWrite>0){m_outBlock=m_localFile->read(qMin(m_bytesToWrite,m_payloadSize));m_bytesToWrite-=(int)m_tcpClient->write(m_outBlock);m_outBlock.resize(0);}else{m_localFile->close();}ui->clientProgressBar->setMaximum(m_totalBytes);ui->clientProgressBar->setValue(m_bytesWritten);if(m_bytesWritten==m_totalBytes){ui->clientStatusLabel->setText(QString("傳送文件 %1 成功").arg(m_fileName));m_localFile->close();m_tcpClient->close();} }void TcpSender::displayError(QAbstractSocket::SocketError){qDebug()<<m_tcpClient->errorString();m_tcpClient->close();ui->clientProgressBar->reset();ui->clientStatusLabel->setText("客戶端就緒");ui->sendButton->setEnabled(true); }void TcpSender::openBtnClicked(){ui->clientProgressBar->reset();ui->clientStatusLabel->setText("狀態:等待打開文件!");openFile(); }void TcpSender::sendBtnClicked(){send(); }TcpSender::~TcpSender() {delete ui; }widget.cpp
#include "widget.h" #include "ui_widget.h"#include <QMessageBox> #include <QHostAddress> #include <QUdpSocket> #include "tcpsender.h" #include "tcpreceiver.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);ui->inputLineEdit->setEnabled(false);ui->sendPushButton->setEnabled(false);ui->peerLineEdit->setEnabled(false);ui->userLineEdit->setEnabled(false);ui->sendFilePushButton->setEnabled(false);connect(ui->userLineEdit,SIGNAL(textChanged(QString)),this,SLOT(widgetEnable(QString)));connect(ui->setPortPushButton,SIGNAL(clicked(bool)),this,SLOT(setPortBtnClickd()));connect(ui->peerLineEdit,SIGNAL(textEdited(QString)),this,SLOT(peerLineEditChange(QString)));connect(ui->sendFilePushButton,SIGNAL(clicked(bool)),this,SLOT(sendFileBtnClicked())); }Widget::~Widget() {delete ui; }void Widget::dataReceived(){while(m_udpSocket->hasPendingDatagrams()){QByteArray datagram;QHostAddress peerIp;datagram.resize(m_udpSocket->pendingDatagramSize());m_udpSocket->readDatagram(datagram.data(),datagram.size(),&peerIp);ui->listWidget->insertItem(0,QString::fromLocal8Bit(datagram.data()));m_peerIp=peerIp.toIPv4Address();QString temp=QString::fromLocal8Bit(datagram.data()).right(4);qDebug()<<"temp:"<<temp;if(temp=="發送文件"){m_tcpReceiver=new TcpReceiver(ui->portLineEdit->text().toInt());m_tcpReceiver->show();}} }void Widget::btnClicked() {QString msg=ui->userLineEdit->text()+QString::fromLocal8Bit(" > ")+ui->inputLineEdit->text();QByteArray datagram=msg.toLocal8Bit();qDebug()<<"msg:"<<msg<<"msg.size"<<msg.size();m_udpSocket->writeDatagram(datagram,datagram.size(),QHostAddress::Broadcast,ui->peerLineEdit->text().toInt());ui->listWidget->insertItem(0,"我 > "+ui->inputLineEdit->text()); }void Widget::widgetEnable(QString data) {if(!data.isEmpty()){ui->inputLineEdit->setEnabled(true);ui->sendPushButton->setEnabled(true);ui->sendFilePushButton->setEnabled(true);} }void Widget::setPortBtnClickd() {m_udpSocket=new QUdpSocket(this);connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));if(!m_udpSocket->bind(ui->portLineEdit->text().toInt(),QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint)){QMessageBox::information(this,"錯誤","端口綁定失敗");return;}connect(ui->sendPushButton,SIGNAL(clicked(bool)),this,SLOT(btnClicked()));ui->peerLineEdit->setEnabled(true); }void Widget::peerLineEditChange(QString data) {if(!data.isEmpty()){ui->userLineEdit->setEnabled(true);} }void Widget::sendFileBtnClicked() {QString msg=ui->userLineEdit->text()+QString::fromLocal8Bit(" > ")+"發送文件";QByteArray datagram=msg.toLocal8Bit();qDebug()<<"msg:"<<msg<<"msg.size"<<msg.size();m_udpSocket->writeDatagram(datagram,datagram.size(),QHostAddress::Broadcast,ui->peerLineEdit->text().toInt());ui->listWidget->insertItem(0,"我 > 發送文件");m_tcpSender=new TcpSender("127.0.0.1",ui->peerLineEdit->text()); //使用本地回環,暫時寫死m_tcpSender->show(); }總結
以上是生活随笔為你收集整理的Qt学习笔记-带TCP数据传输的局域网聊天软件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt工作笔记-XML文件的写入
- 下一篇: Qt工作笔记-QGraphics框架场景