东莞网站开发营销,最近新闻内容,wordpress用什么空间 曹鹏,个人怎样申请注册公司QT tcp与udp网络通信以及定时器的使用 文章目录 QT tcp与udp网络通信以及定时器的使用1、QT网络与通信简单介绍2、QT TCP通信1、 服务器的流程2、 客户端的流程3、服务器的编写4、客户端的编写 3、QT UDP通信1、客户端流程2、客户端编写3、UDP广播4、UDP组播 4、定时器的用法1、…QT tcp与udp网络通信以及定时器的使用 文章目录 QT tcp与udp网络通信以及定时器的使用1、QT网络与通信简单介绍2、QT TCP通信1、 服务器的流程2、 客户端的流程3、服务器的编写4、客户端的编写 3、QT UDP通信1、客户端流程2、客户端编写3、UDP广播4、UDP组播 4、定时器的用法1、方法一2、方法22、方法3不建议使用 5、Tcp传文件1、服务器编写2、客户端编写 6、tcp与udp对比7.总结 1、QT网络与通信简单介绍
QT5提供了一套完善的网络模块包括了TCP、UDP、HTTP等协议的支持可以方便地在QT应用程序中进行网络通信。通过QT5的网络模块开发者可以实现客户端和服务器之间的数据传输、消息推送、远程控制等功能。 Qt中提供的所有的Socket类都是非阻塞的。 Qt中常用的用于socket通信的套接字类: QTcpServer 用于TCP/IP通信, 作为服务器端套接字使用 QTcpSocket 用于TCP/IP通信作为客户端套接字使用。 QUdpSocket 用于UDP通信服务器客户端均使用此套接字。 QSslSocket 用于实现安全的网络通信、 QWebSocket 用于实现WebSocket协议的通信等。 下面是继承关系
2、QT TCP通信
TCP协议传输控制协议英语Transmission Control Protocol缩写为TCP是一种面向连接的、可靠的、基于字节流的通信协议。分为服务器与客户端。
1、 服务器的流程 2、 客户端的流程 总体双方的流程如下
3、服务器的编写
完成的结果如下客户端点击连接服务器按钮。成功连接就可以相互进行通信了。
注意要使用QT的网络模块需要在.pro文件中添加QT network声明以添加网络模块的依赖。
声明TCP监听套接字与通信套接字
#include QTcpServer
#include QTcpSocket
QTcpServer *pTcpListenSocket nullptr;
QTcpSocket *pTcpCommunicatSocket nullptr;创建QTcpServer套接字。QTcpSocket套接字在客户端成功连接时获取。此时为空。
pTcpListenSocket new QTcpServer(this);
pTcpCommunicatSocket nullptr;监听客户端连接请求并处理
pTcpListenSocket-listen(QHostAddress::Any, 7777); /* 服务器地址和端口 */获取通信套接字
/* 取出建立好的连接套接字 */pTcpCommunicatSocket pTcpListenSocket-nextPendingConnection();最后就可以进行发送接收数据
/* 发送给客户端数据接口 */
pTcpCommunicatSocket-write(sendData);
/* 接收客户端的数据接口 */
QByteArray arry pTcpCommunicatSocket-readAll();断开连接
pTcpClientSocket-disconnectFromHost();
pTcpClientSocket-close();服务器整体的代码如下 首先Ui的布局 serveridget.h
#include QWidget
#include QTcpServer
#include QTcpSocketQT_BEGIN_NAMESPACE
namespace Ui { class Serveridget; }
QT_END_NAMESPACEclass Serveridget : public QWidget
{Q_OBJECTpublic:Serveridget(QWidget *parent nullptr);~Serveridget();QString ip;quint16 port;
private:QTcpServer *pTcpListenSocket nullptr;QTcpSocket *pTcpCommunicatSocket nullptr;
private slots:void ConnecSucceSlot(void);void ReceDealSlot(void);void SendDataSlot(void);void DisServerSlot(void);void ClearReceSlot(void);void ClearSendSlot(void);
private:Ui::Serveridget *ui;
};serveridget.cpp
#include serveridget.h
#include ui_serveridget.h
#include QPushButton
#include QDebugServeridget::Serveridget(QWidget *parent): QWidget(parent), ui(new Ui::Serveridget)
{ui-setupUi(this);pTcpListenSocket new QTcpServer(this);this-setWindowTitle(服务器端口7777);this-resize(400,400);ui-textEditRead-setPlaceholderText(接收区);pTcpListenSocket-listen(QHostAddress::Any, 7777); /* 服务器地址和端口 *//* 客户端与服务器连接成功监听套接字会触发newConnection */connect(pTcpListenSocket, QTcpServer::newConnection, this, Serveridget::ConnecSucceSlot);/* 服务器发送数据 */connect(ui-pushButtonSendData, QPushButton::pressed, this, Serveridget::SendDataSlot);/* 断开与客户端的连接 */connect(ui-pushButtonClose, QPushButton::pressed, this, Serveridget::DisServerSlot);/* 清空接收区 */connect(ui-pushButtonClearSend, QPushButton::pressed, this, Serveridget::ClearSendSlot);/* 清空发送区 */connect(ui-pushButtonClearReceive, QPushButton::pressed, this, Serveridget::ClearReceSlot);}Serveridget::~Serveridget()
{delete ui;
}void Serveridget::ConnecSucceSlot(void)
{/* 取出建立好的连接套接字 */pTcpCommunicatSocket pTcpListenSocket-nextPendingConnection();/* 获取连接成功客户端的ip与端口 */ip pTcpCommunicatSocket-peerAddress().toString();port pTcpCommunicatSocket-peerPort();QString str QString([%1]:[%2]:[%3]:连接成功).arg(ip).arg(port); /* 组包 */ui-textEditRead-setText(str); /* 显示连接成功 *//* 当客户端发送数据服务器成功接收通信套接字触发readyRead信号 */connect(pTcpCommunicatSocket, QTcpSocket::readyRead, this, Serveridget::ReceDealSlot);
}void Serveridget::ReceDealSlot(void)
{if (pTcpCommunicatSocket nullptr) {return;}/* 接收客户端的数据 */QByteArray arry pTcpCommunicatSocket-readAll();/* 显示数据 */ui-textEditRead-append(arry);
}void Serveridget::SendDataSlot(void)
{if (pTcpCommunicatSocket nullptr) {return;}/* 获取发送的数据 */QByteArray sendData ui-textEditWrite-toPlainText().toUtf8().data();/* 发送的数据 */pTcpCommunicatSocket-write(sendData);
}void Serveridget::DisServerSlot(void)
{if (pTcpCommunicatSocket nullptr) {return;}/* 主动和客户端端口连接 */pTcpCommunicatSocket-disconnectFromHost();pTcpCommunicatSocket-close();pTcpCommunicatSocket nullptr;QString str QString([%1]:[%2]:断开连接).arg(ip).arg(port); /* 组包 */ui-textEditRead-setText(str); /* 显示连接成功 */
}void Serveridget::ClearReceSlot(void)
{ui-textEditRead-clear();
}void Serveridget::ClearSendSlot(void)
{ui-textEditWrite-clear();
}
4、客户端的编写
声明TCP通信套接字
#include QTcpSocket
QTcpSocket *pTcpClientSocket nullptr;创建TCP通信套接字
pTcpClientSocket new QTcpSocket(this);主动与服务器建立连接
/* 主动与服务器建立连接 */
pTcpClientSocket-connectToHost(QHostAddress(ip), port);读写数据
/* 发送数据给服务器 */
pTcpClientSocket-write(sendData);
/* 接收服务器的数据 */
QByteArray arry pTcpClientSocket-readAll();断开连接
pTcpClientSocket-disconnectFromHost();
pTcpClientSocket-close();客户端整体的代码如下 首先Ui的布局 客户端的创建
clientwidget.h
#include QWidget
#include QTcpSocket
namespace Ui {
class Clientwidget;
}
class Clientwidget : public QWidget
{Q_OBJECTpublic:explicit Clientwidget(QWidget *parent nullptr);~Clientwidget();QTcpSocket *pTcpClientSocket nullptr;
private slots:void ConnectServerSlot(void);void ConnectSucceSlot(void);void SendDataSlot(void);void ReadDataSlot(void);void DisconnectSlot(void);void DisconnecServerSlot(void);void ClearReceSlot(void);void ClearSendSlot(void);
private:Ui::Clientwidget *ui;
};clientwidget.cpp
#include clientwidget.h
#include ui_clientwidget.h
#include QPushButton
#include QHostAddressClientwidget::Clientwidget(QWidget *parent) :QWidget(parent),ui(new Ui::Clientwidget)
{ui-setupUi(this);pTcpClientSocket new QTcpSocket(this);this-setWindowTitle(客户端);this-resize(400,400);ui-textEditRead-setPlaceholderText(接收区);/* 主动与服务器连接 */connect(ui-pushButtonConnect, QPushButton::pressed, this, Clientwidget::ConnectServerSlot);/* 如果成功与服务器建立连接通信套接字触发connected */connect(pTcpClientSocket, QTcpSocket::connected, this, Clientwidget::ConnectSucceSlot);/* 如果成功与服务器断开连接通信套接字触发disconnected */connect(pTcpClientSocket, QTcpSocket::disconnected, this, Clientwidget::DisconnectSlot);/* 接收服务器的数据 */connect(pTcpClientSocket, QTcpSocket::readyRead, this, Clientwidget::ReadDataSlot);/* 发送数据 */connect(ui-pushButtonsendData, QPushButton::pressed, this, Clientwidget::SendDataSlot);/* 断开与客户端的连接 */connect(ui-pushButtonDisconnec, QPushButton::pressed,this, Clientwidget::DisconnecServerSlot);/* 清空接收区 */connect(ui-pushButtonClearSend, QPushButton::pressed, this, Clientwidget::ClearSendSlot);/* 清空发送区 */connect(ui-pushButtonClearRece, QPushButton::pressed, this, Clientwidget::ClearReceSlot);
}Clientwidget::~Clientwidget()
{delete ui;
}void Clientwidget::ConnectServerSlot(void)
{/* 获取服务器ip和端口 */QString ip ui-lineEditIP-text();qint16 port ui-lineEditPort-text().toInt();/* 主动与服务器建立连接 */pTcpClientSocket-connectToHost(QHostAddress(ip), port);
}
void Clientwidget::ConnectSucceSlot(void)
{ui-textEditRead-append(成功与客户端连接);
}
void Clientwidget::SendDataSlot(void)
{/* 获取发送的数据 */QByteArray sendData ui-textEditWrite-toPlainText().toUtf8().data();pTcpClientSocket-write(sendData);
}
void Clientwidget::ReadDataSlot(void)
{QByteArray arry pTcpClientSocket-readAll();ui-textEditRead-append(arry);
}
void Clientwidget::DisconnectSlot(void)
{ui-textEditRead-append(断开与客户端连接);
}
void Clientwidget::DisconnecServerSlot(void)
{if (pTcpClientSocket nullptr) {return;}pTcpClientSocket-disconnectFromHost();pTcpClientSocket-close();
}
void Clientwidget::ClearReceSlot(void)
{ui-textEditRead-clear();
}
void Clientwidget::ClearSendSlot(void)
{ui-textEditWrite-clear();
}main.cpp
#include serveridget.h
#include clientwidget.h
#include QApplication
int main(int argc, char *argv[])
{QApplication a(argc, argv);Serveridget serverWid;Clientwidget clientWid;serverWid.show();clientWid.show();return a.exec();
}3、QT UDP通信
使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下客户端并不与服务器建立连接它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接只负责调用接收函数等待来自客户端的数据的到达。 在UDP通信中服务器端和客户端的概念已经显得有些淡化两部分做的工作都大致相同.
1、客户端流程 创建其它的客户端也是一样的流程。 总体双方的流程如下
2、客户端编写
注意要使用QT的网络模块需要在.pro文件中添加QT network声明以添加网络模块的依赖。 最后的效果如下
客户端的ui界面:
声明UDP通信套接字
#include QUdpSocket
QUdpSocket *pUdpSocket nullptr;创建UDP通信套接字
pUdpSocket new QUdpSocket(this);绑定端口
pUdpSocket-bind(QHostAddress::Any,7777);读写数据
/* 获取数据 */pUdpSocket-writeDatagram(sendData, QHostAddress(strIP), port);
/* 读取对方发送的内容 */
char buf[1024] {0}; /* 保存对方的数据 */
QHostAddress cliAddr; /* 对方地址 */
quint16 port; /* 对方端口 */
qint64 size pUdpSocket-readDatagram(buf, sizeof(buf), cliAddr, port);总体的代码如下 clientwidget.h
#include QWidget
#include QUdpSocket
QT_BEGIN_NAMESPACE
namespace Ui { class ClientWidget; }
QT_END_NAMESPACE
class ClientWidget : public QWidget
{Q_OBJECTpublic:ClientWidget(QWidget *parent nullptr);~ClientWidget();QUdpSocket *pUdpSocket nullptr;
private slots:void ReadDataSlot(void);void WriteDataSlot(void);
private:Ui::ClientWidget *ui;
};clientwidget.cpp
#include clientwidget.h
#include ui_clientwidget.h
#include QPushButton
#include QDebugClientWidget::ClientWidget(QWidget *parent): QWidget(parent), ui(new Ui::ClientWidget)
{ui-setupUi(this);pUdpSocket new QUdpSocket(this);/* 绑定端口 */pUdpSocket-bind(QHostAddress::Any,7777);this-setWindowTitle(服务器端口7777);this-resize(400,400);ui-textEditRece-setPlaceholderText(接收区);/* 发送数据 */connect(ui-pushButtonSend, QPushButton::pressed, this, ClientWidget::WriteDataSlot);/* 接收到readyRead信号 */connect(pUdpSocket, QUdpSocket::readyRead, this, ClientWidget::ReadDataSlot);
}ClientWidget::~ClientWidget()
{delete ui;
}
void ClientWidget::WriteDataSlot(void)
{/* 获取发送对方的端口与IP */QString strIP ui-lineEditIP-text();qint16 port ui-lineEditPort-text().toInt();QByteArray sendData ui-textEditSend-toPlainText().toUtf8().data();if (strIP.isEmpty() || sendData.size() 0) {qDebug() isEmpty;return;}/* 获取数据 */pUdpSocket-writeDatagram(sendData, QHostAddress(strIP), port);
}void ClientWidget::ReadDataSlot(void)
{/* 读取对方发送的内容 */char buf[1024] {0}; /* 保存对方的数据 */QHostAddress cliAddr; /* 对方地址 */quint16 port; /* 对方端口 */qint64 size pUdpSocket-readDatagram(buf, sizeof(buf), cliAddr, port);qDebug() size:size;if (size 0) {/* 格式化 [192.68.2.2:8888]aaaa */QString str QString([%1:%2] %3).arg(cliAddr.toString()).arg(port).arg(buf);ui-textEditRece-append(str);}
}例外一端是一样的。把绑定端口换一下就行。
pUdpSocket-bind(QHostAddress::Any,8888);3、UDP广播 4、UDP组播 注意组播在绑定是IP要选择QHostAddress::AnyIPv4 并且组播是D类地址。 udpSocket-leaveMulticastGroup(QHostAddress(“224.0.0.2”)) 如果不想接收也可以退出这个组播。
4、定时器的用法
1、方法一
最后的效果 只是简单使用两个不同的定时器。 1、定义一个QTimer对象
QTimer* timer;
timer new QTimer(this);启动定时器
timer-start(1000)3 . 连接信号槽 当start启动定时器就会每隔设定的时间触发timeout信号
connect(timer, QTimer::timeout,[](){/* 定时器时间到的处理 */});停止计时
timer-stop();mywidget.h
#include QWidget
#include QTimer
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACEclass MyWidget : public QWidget
{Q_OBJECT
public:MyWidget(QWidget *parent nullptr);~MyWidget();QTimer *pTime_1;QTimer *pTime_2;int i 0;int j 0;private slots:void on_pushButtonStartOne_clicked();void on_pushButtonStartTwo_clicked();void on_pushButtonStopOne_clicked();void on_pushButtonStoptwo_clicked();private:Ui::MyWidget *ui;
};mywidget.cpp
#include mywidget.h
#include ui_mywidget.hMyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);pTime_1 new QTimer(this);pTime_2 new QTimer(this);i 0;j 0;connect(pTime_1, QTimer::timeout,[](){i;ui-lcdNumberOne-display(i);});connect(pTime_2, QTimer::timeout,[](){j;ui-lcdNumberTwo-display(j);});
}MyWidget::~MyWidget()
{delete ui;
}
void MyWidget::on_pushButtonStartOne_clicked()
{//启动定时器//时间间隔为1s//每隔1s,定时器pTime_1自动触发timeout()//如果定时器没有激活才启动if(pTime_1-isActive() false){pTime_1-start(1000);}
}void MyWidget::on_pushButtonStartTwo_clicked()
{if(pTime_2-isActive() false){pTime_2-start(1000);}
}void MyWidget::on_pushButtonStopOne_clicked()
{if(pTime_1-isActive() true){pTime_1-stop();}
}void MyWidget::on_pushButtonStoptwo_clicked()
{if(pTime_2-isActive() true){pTime_2-stop();}
}2、方法2
1、重写虚函数
void timerEvent(QTimerEvent* e);2、启动定时器
/* 返回定时器的Id 并且是唯一的 就是区分不同定时器 */
timeId_1 startTimer(1000); 定时器时间到进入timerEvent事件
void MyWidget::timerEvent(QTimerEvent *e)
{static int i 0;static int j 0;if (e-timerId() timeId_1) {ui-lcdNumberOne-display(i);} else if (e-timerId() timeId_2) {ui-lcdNumberTwo-display(j);}
}关闭定时器
killTimer(timeId_1);mywidget.h
#include QWidget
#include QTimerEventQT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACEclass MyWidget : public QWidget
{Q_OBJECTpublic:MyWidget(QWidget *parent nullptr);~MyWidget();int timeId_1 0;int timeId_2 0;
protected:void timerEvent(QTimerEvent *e);
private slots:void on_pushButtonStartOne_clicked();void on_pushButtonStartTwo_clicked();void on_pushButtonStopOne_clicked();void on_pushButtonStoptwo_clicked();private:Ui::MyWidget *ui;
};mywidget.cpp
#include mywidget.h
#include ui_mywidget.hMyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::timerEvent(QTimerEvent *e)
{static int i 0;static int j 0;if (e-timerId() timeId_1) {ui-lcdNumberOne-display(i);} else if (e-timerId() timeId_2) {ui-lcdNumberTwo-display(j);}
}void MyWidget::on_pushButtonStartOne_clicked()
{//启动定时器//时间间隔为1000ms//每隔1s,进入timerEvent事件timeId_1 startTimer(1000);
}void MyWidget::on_pushButtonStartTwo_clicked()
{timeId_2 startTimer(4000);
}void MyWidget::on_pushButtonStopOne_clicked()
{killTimer(timeId_1);
}void MyWidget::on_pushButtonStoptwo_clicked()
{killTimer(timeId_2);
}
2、方法3不建议使用
singleShot静态函数 原型void QTimer::singleShot(int msec, const QObject *receiver, const char *member) 解释这个静态函数在一个给定时间间隔 msec(毫秒) 之后调用一个槽。 只调一次 假设类A有个槽函数 function() { } 我们要在1s之后执行它
QTimer::singleShot(1000,this, A::function())实现循环 槽函数中还是singleShot 即 这样的话就是一个每1秒执行一次的定时器
bool condition true;
function(){if(condition){ //条件控制QTimer::singleShot(1000,this, A::function());}
}5、Tcp传文件
具体的流程图如下 最终的效果如下 注意要使用QT的网络模块需要在.pro文件中添加QT network声明以添加网络模块的依赖。
1、服务器编写
服务器ui的设计 serverwidget.h
#include QWidget
#include QTcpServer
#include QTcpSocket
#include QFile
#include QTimernamespace Ui {
class ServerWidget;
}class ServerWidget : public QWidget
{Q_OBJECTpublic:explicit ServerWidget(QWidget *parent 0);~ServerWidget();void sendData(); //发送文件数据private slots:void on_buttonFile_clicked();void on_buttonSend_clicked();
private:Ui::ServerWidget *ui;QTcpServer *tcpServer; //监听套接字QTcpSocket *tcpSocket; //通信套接字QFile file; //文件对象QString fileName; //文件名字qint64 fileSize; //文件大小qint64 sendSize; //已经发送文件的大小QTimer timer; //定时器};
serverwidget.cpp
#include serverwidget.h
#include ui_serverwidget.h
#include QFileDialog#include QFileInfoServerWidget::ServerWidget(QWidget *parent) :QWidget(parent),ui(new Ui::ServerWidget)
{ui-setupUi(this);/* 创建监听套接字 */tcpServer new QTcpServer(this);/* 监听 */tcpServer-listen(QHostAddress::Any, 8888);/* 设置窗口标题 */setWindowTitle(服务器端口为8888);/* 失能两个按钮都不能按 连接成功才可以按 */ui-buttonFile-setEnabled(false);ui-buttonSend-setEnabled(false);//如果客户端成功和服务器连接//tcpServer会自动触发 newConnection()connect(tcpServer, QTcpServer::newConnection,[](){//取出建立好连接的套接字tcpSocket tcpServer-nextPendingConnection();//获取对方的ip和端口QString ip tcpSocket-peerAddress().toString();quint16 port tcpSocket-peerPort();QString str QString([%1:%2] 成功连接).arg(ip).arg(port);ui-textEdit-setText(str); //显示到编辑区//成功连接后才能按选择文件ui-buttonFile-setEnabled(true);connect(tcpSocket, QTcpSocket::readyRead,[](){//取客户端的信息QByteArray buf tcpSocket-readAll();/* 接收到客户端file done 说明客户端接收完成 */if(QString(buf) file done){ //文件接收完毕ui-textEdit-append(文件发送完毕);file.close();//断开客户端端口tcpSocket-disconnectFromHost();tcpSocket-close();}});});connect(timer, QTimer::timeout,[](){//关闭定时器timer.stop();//发送文件数据sendData();});}ServerWidget::~ServerWidget()
{delete ui;
}//选择文件的按钮
void ServerWidget::on_buttonFile_clicked()
{QString filePath QFileDialog::getOpenFileName(this, open, ../);if(false filePath.isEmpty()) //如果选择文件路径有效{fileName.clear();fileSize 0;QFileInfo info(filePath);//获取文件信息fileName info.fileName(); //获取文件名字fileSize info.size(); //获取文件大小sendSize 0; //发送文件的大小//只读方式打开文件//指定文件的名字file.setFileName(filePath);//打开文件bool isOk file.open(QIODevice::ReadOnly);if(false isOk){qDebug() 只读方式打开文件失败 106;}//提示打开文件的路径ui-textEdit-append(filePath);ui-buttonFile-setEnabled(false);ui-buttonSend-setEnabled(true);}else{qDebug() 选择文件路径出错 118;}}
//发送文件按钮
void ServerWidget::on_buttonSend_clicked()
{ui-buttonSend-setEnabled(false);//先发送文件头信息 格式:文件名##文件大小QString head QString(%1##%2).arg(fileName).arg(fileSize);//发送头部信息qint64 len tcpSocket-write( head.toUtf8() );if(len 0)//头部信息发送成功{//发送真正的文件信息//防止TCP黏包//需要通过定时器延时 20 ms 在发送文件数据timer.start(20);}else{qDebug() 头部信息发送失败 142;file.close();ui-buttonFile-setEnabled(true);ui-buttonSend-setEnabled(false);}
}void ServerWidget::sendData()
{ui-textEdit-append(正在发送文件……);qint64 len 0;do{//每次发送数据的大小 4Kchar buf[4*1024] {0};len 0;//往文件中读数据len file.read(buf, sizeof(buf));//发送数据读多少发多少len tcpSocket-write(buf, len);//发送的数据需要累积sendSize len;}while(len 0);}
2、客户端编写
客户端ui的设计 功能当客户端与服务器成功连接后。服务器选择发送一个文件给客户端。 clientwidget.h
#include QWidget
#include QTcpSocket
#include QFilenamespace Ui {
class ClientWidget;
}class ClientWidget : public QWidget
{Q_OBJECT
public:explicit ClientWidget(QWidget *parent 0);~ClientWidget();
private slots:void on_buttonConnect_clicked();
private:Ui::ClientWidget *ui;QTcpSocket *tcpSocket;QFile file; //文件对象QString fileName; //文件名字qint64 fileSize; //文件大小qint64 recvSize; //已经接收文件的大小bool isStart; //标志位是否为头部信息
};clientwidget.cpp
#include clientwidget.h
#include ui_clientwidget.h
//#include QDebug
#include QMessageBox
#include QHostAddressClientWidget::ClientWidget(QWidget *parent) :QWidget(parent),ui(new Ui::ClientWidget)
{ui-setupUi(this);tcpSocket new QTcpSocket(this);isStart true;ui-progressBar-setValue(0); //当前值setWindowTitle(客户端);connect(tcpSocket, QTcpSocket::connected,[](){//提示连接成功ui-textEdit-clear();ui-textEdit-append(和服务器连接成功等待服务器传送文件……);});connect(tcpSocket, QTcpSocket::readyRead,[](){//取出接收的内容QByteArray buf tcpSocket-readAll();if(true isStart){//接收头isStart false;//解析头部信息 QString buf hello##1024// QString str hello##1024#mike;// str.section(##, 0, 0)//初始化//文件名fileName QString(buf).section(##, 0, 0);//文件大小fileSize QString(buf).section(##, 1, 1).toInt();recvSize 0; //已经接收文件大小//打开文件//关联文件名字file.setFileName(fileName);//只写方式方式打开文件bool isOk file.open(QIODevice::WriteOnly);if(false isOk){qDebug() WriteOnly error 49;tcpSocket-disconnectFromHost(); //断开连接tcpSocket-close(); //关闭套接字return; //如果打开文件失败退出。}//弹出对话框显示接收文件的信息QString str QString(接收的文件: [%1: %2kb]).arg(fileName).arg(fileSize/1024);//QMessageBox::information(this, 文件信息, str);ui-textEdit-append(str);ui-textEdit-append(正在接收文件……);//设置进度条ui-progressBar-setMinimum(0); //最小值ui-progressBar-setMaximum(fileSize/1024); //最大值ui-progressBar-setValue(0); //当前值}else //文件信息{qint64 len file.write(buf);if(len 0) //接收数据大于0{recvSize len; //累计接收大小qDebug() len;}//更新进度条ui-progressBar-setValue(recvSize/1024); // 1024:防止文件太大越界 / 1024if(recvSize fileSize) //文件接收完毕{//先给服务发送(接收文件完成的信息)tcpSocket-write(file done);ui-textEdit-append(文件接收完成);QMessageBox::information(this, 完成, 文件接收完成);file.close(); //关闭文件//断开连接tcpSocket-disconnectFromHost();tcpSocket-close();}}});
}ClientWidget::~ClientWidget()
{delete ui;
}void ClientWidget::on_buttonConnect_clicked()
{//获取服务器的ip和端口QString ip ui-lineEditIP-text();quint16 port ui-lineEditPort-text().toInt();//主动和服务器连接tcpSocket-connectToHost(QHostAddress(ip), port);isStart true;//设置进度条ui-progressBar-setValue(0);
}
6、tcp与udp对比 7.总结
以上就是今天要讲的内容本文简单介绍了QT的Tcp与udp网络通信。tcp传输文件的案列。以及定时器的多种用法