[QT] TCP协议演示

一个 文件传说 的东西...

先看 发送 的..

头文件

header.h

#ifndef HEADER_H #define HEADER_H #include <QDialog> #include <QTcpSocket> #include <QAbstractSocket> class QTcpSocket; class QDialogButtonBox; class QDialog; class QFile; class QProgressBar; class QLabel; class QVBoxLayout; class QTimer; class Dialog:public QDialog{ Q_OBJECT public: Dialog(QWidget *parent=0); public slots: void start(); void quit(); void startTransfer(); void updateClientProgress(qint64 numBytes); void displayError(QAbstractSocket::SocketError socketError); void openFile(); void connectError(); private : QProgressBar *clientProgressBar; QLabel *clientStatusLabel; QPushButton *startButton; QPushButton *quitButton; QPushButton *openButton; QDialogButtonBox *buttonBox; QVBoxLayout *mainLayout; QTcpSocket tcpClient; int flag; qint64 TotalBytes; qint64 bytesWritten; qint64 bytesToWrite; qint64 localSize; QTimer *timer; QString fileName; QFile *localFile; QByteArray outBlock; }; #endif // HEADER_H

main.cpp

#include <QtGui> #include <QHostAddress> #include "header.h" //构造函数 一些初始化操作 Dialog::Dialog(QWidget *parent):QDialog(parent){ localSize=4*1024; TotalBytes=0; bytesWritten=0; bytesToWrite=0; setWindowTitle(tr("发送文件")); clientProgressBar=new QProgressBar; clientStatusLabel=new QLabel(tr("客户端准备完毕")); startButton=new QPushButton(tr("开始")); quitButton=new QPushButton(tr("退出")); openButton=new QPushButton(tr("打开")); startButton->setEnabled(false); buttonBox=new QDialogButtonBox; buttonBox->addButton(startButton,QDialogButtonBox::ActionRole); buttonBox->addButton(openButton,QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton,QDialogButtonBox::RejectRole); mainLayout=new QVBoxLayout; mainLayout->addWidget(clientProgressBar); mainLayout->addWidget(clientStatusLabel); mainLayout->addWidget(buttonBox); setLayout(mainLayout); connect(startButton,SIGNAL(clicked()),this,SLOT(start())); connect(openButton,SIGNAL(clicked()),this,SLOT(openFile())); connect(quitButton,SIGNAL(clicked()),this,SLOT(quit())); timer=new QTimer(this); // connect(timer,SIGNAL(timeout()),this,SLOT(connectError())); connect(&tcpClient,SIGNAL(connected()),this,SLOT(startTransfer())); connect(&tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64))); connect(&tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError))); flag=1; } //连接超时错误 void Dialog::connectError(){ } //退出 void Dialog::quit(){ qApp->quit(); } //开始连接服务器 void Dialog::start(){ timer->start(1000); startButton->setEnabled(false); QApplication::setOverrideCursor(Qt::WaitCursor); bytesWritten=0; clientStatusLabel->setText(tr("连接中")); tcpClient.connectToHost(QHostAddress::LocalHost,8888); } //打开文件 void Dialog::openFile(){ fileName=QFileDialog::getOpenFileName(this); if(!fileName.isEmpty()){ startButton->setEnabled(true); } } void Dialog::startTransfer(){ //只读方式打开文件 localFile=new QFile(fileName); if(!localFile->open(QFile::ReadOnly)){ QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件").arg(fileName).arg(localFile->errorString())); return ; } //获取 文件大小 TotalBytes=localFile->size(); //发送缓冲区outBlock封装在一个QDataStream类型变量中 QDataStream sendOut(&outBlock,QIODevice::WriteOnly); //设置流化数据版本 sendOut.setVersion(QDataStream::Qt_4_6); //通过.right去掉 文件的路径部分, //fileName.lastIndexOf('/')返回的是 文件最后一个 / 所在的位数(INT) //fileName.right()返回的是 从右面开始数 的位数的值. //例如 路径如果是D:/My Documents/Tcp/header.h //fileName.lastIndexOf('/')返回的是从D开始 到最后一个 / 的位数 //fileName.right(8) 意思就是 从路径右面开始 到第八位数的字符串 QString currentFile=fileName.right(fileName.size()-fileName.lastIndexOf('/')-1); //构造一个临时文件头 将总长度和文件名长度暂时为0 sendOut<<qint64(0)<<qint64(0)<<currentFile; //获得文件头的实际存储大小 追加到 TotalBytes; TotalBytes+=outBlock.size(); //将读写操作指向文件头. sendOut.device()->seek(0); //填写实际总长度和文件长度 sendOut<<TotalBytes<<qint64((outBlock.size()-sizeof(qint64)*2)); //调用 write函数将文件头发出同时修改 bytesToWrite; bytesToWrite=TotalBytes-tcpClient.write(outBlock); clientStatusLabel->setText(tr("已经连接")); qDebug()<<currentFile<<TotalBytes; //清空缓冲区 outBlock.resize(0); } //数据发出 将会产生 bytesWritten()信号 然后调用此方法 参数表示实际已发出的字节 void Dialog::updateClientProgress(qint64 numBytes){ bytesWritten+=(int)numBytes; if(bytesToWrite>0){ outBlock=localFile->read(qMin(bytesToWrite,localSize)); bytesToWrite-=(int)tcpClient.write(outBlock); outBlock.resize(0); }else{ localFile->close(); } clientProgressBar->setMaximum(TotalBytes); clientProgressBar->setValue(bytesWritten); clientStatusLabel->setText(tr("已发送 %1 M").arg(bytesWritten/(1024*1024))); } //链接错误方法 void Dialog::displayError(QAbstractSocket::SocketError socketError){ if(socketError=QTcpSocket::RemoteHostClosedError) return; QMessageBox::information(this,tr("网络"),tr("产生如下错误: %1.").arg(tcpClient.errorString())); tcpClient.close(); clientProgressBar->reset(); clientStatusLabel->setText(tr("客户端就绪")); startButton->setEnabled(true); QApplication::restoreOverrideCursor(); } int main(int argc,char **argv){ QApplication app(argc,argv); QTextCodec::setCodecForTr( QTextCodec::codecForName("gb2312")); Dialog dialog; dialog.show(); return app.exec(); }

再看 接受文件

header.h

#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QTcpServer> class QFile; class QDialogButtonBox; class QLabel; class QProgressBar; class QPushButton; class QTcpSocket; class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); public slots: void start(); void acceptConnection(); void updateServerProgress(); void displayError(QAbstractSocket::SocketError socketError); private: QProgressBar *clientProgressBar; QProgressBar *serverProgressBar; QLabel *serverStatusLabel; QPushButton *startButton; QPushButton *quitButton; QPushButton *openButton; QDialogButtonBox *buttonBox; QTcpServer tcpServer; QTcpSocket *tcpServerConnection; qint64 TotalBytes; qint64 bytesReceived; qint64 fileNameSize; QString fileName; QFile *localFile; QByteArray inBlock; }; #endif

再看 实现文件

dialog.cpp

#include "receiver.h" #include <QtNetwork> Receiver::Receiver(QObject *parent) : QObject(parent) { udpSocket = new QUdpSocket(this); udpSocket->bind(44444); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); } void Receiver::processPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); qDebug()<<(tr("接收数据: /"%1/"") .arg(datagram.data())); } }

然后是 main.cpp

#include <QApplication> #include <QtCore> #include "dialog.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QTextCodec::setCodecForTr( QTextCodec::codecForName("gb2312")); Dialog dialog; dialog.show(); return dialog.exec(); }

执行结果如下..

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值