qt之网络协议
tcp:
// -------------- widget.h: #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpServer> //服务器 #include <QTcpSocket> // 套接字 发送的消息 namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); QTcpServer* _tcpServer = NULL; QTcpSocket* _tcpSocket = NULL; private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H // -------------- widget.cpp: #include "widget.h" #include "ui_widget.h" #include <QHostAddress> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); setWindowTitle("服务端:8888"); //_tcpSocket = new QTcpSocket(this); _tcpServer = new QTcpServer(this); _tcpServer->listen(QHostAddress::Any,8888); // 服务第的ip和端口 connect(_tcpServer, &QTcpServer::newConnection, [=](){ // 有人连接时触发 _tcpSocket = _tcpServer->nextPendingConnection(); // 获取对方套接字,包含对方的基础信息 QString ip = _tcpSocket->peerAddress().toString(); // 通过套接字获取对方的iP qint16 port = _tcpSocket->peerPort(); // 通过套接字获取对方的端口 QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port); ui->textEdit->setText(temp); connect(_tcpSocket,&QTcpSocket::readyRead,[=](){ // 接收消息,对方连接我成功后方可接收 QByteArray array = _tcpSocket->readAll(); ui->textEdit->append(array); }); }); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() //给客户端发数据 { if(_tcpSocket == NULL) return; QString str = ui->textEdit_2->toPlainText(); _tcpSocket->write(str.toUtf8().data()); } void Widget::on_pushButton_2_clicked() // 和客户端断开连接 { if(_tcpSocket == NULL) return; _tcpSocket->disconnectFromHost(); _tcpSocket->close(); _tcpSocket = NULL; } // -------------- socket.h: #ifndef SOCKET_H #define SOCKET_H #include <QWidget> #include <QTcpSocket> namespace Ui { class socket; } class socket : public QWidget { Q_OBJECT public: explicit socket(QWidget *parent = 0); ~socket(); QTcpSocket* _tcpSocket = NULL; private slots: void on_pushButton_2_clicked(); void on_pushButton_3_clicked(); void on_pushButton_clicked(); private: Ui::socket *ui; }; #endif // SOCKET_H // -------------- socket.cpp: #include "socket.h" #include "ui_socket.h" #include <QHostAddress> socket::socket(QWidget *parent) : QWidget(parent), ui(new Ui::socket) { ui->setupUi(this); _tcpSocket = new QTcpSocket(this); // 分配空间,指定父对象 connect(_tcpSocket,&QTcpSocket::connected,[=](){ // 和服务器连接时触发 ui->textEdit->setText("成功和服务器连接"); connect(_tcpSocket,&QTcpSocket::readyRead,[=](){ // 接收消息,这里写在外面也没关系,反正_tcpSocket接收到消息了就触发 QByteArray array = _tcpSocket->readAll(); ui->textEdit->append(array); }); }); } socket::~socket() { delete ui; } void socket::on_pushButton_clicked() // 连接服务器 { QString ip = ui->lineEdit->text(); qint16 port = ui->lineEdit_2->text().toInt(); _tcpSocket->connectToHost(QHostAddress(ip),port); } void socket::on_pushButton_2_clicked() // 发送数据 { if(_tcpSocket == NULL) return; QString str = ui->textEdit_2->toPlainText(); _tcpSocket->write(str.toUtf8().data()); } void socket::on_pushButton_3_clicked() // 断开连接 { if(_tcpSocket == NULL) return; _tcpSocket->disconnectFromHost(); _tcpSocket->close(); _tcpSocket = NULL; }
// ----------------------- widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpServer> //服务器 #include <QTcpSocket> // 套接字 发送的消息 #include <QFile> #include <QTimer> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); QTcpServer* _tcpServer = NULL; QTcpSocket* _tcpSocket = NULL; QFile file; QString fileName; qint64 fileSize; qint64 sendSize; QTimer timer; void sendData(); private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H // ----------------------- widget.cpp #include "widget.h" #include "ui_widget.h" #include <QFileDialog> #include <QDebug> #include <QFileInfo> // 获取文件信息 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); setWindowTitle("服务端:8888"); // 没连接时按钮不能按 ui->pushButton->setEnabled(false); ui->pushButton_2->setEnabled(false); //_tcpSocket = new QTcpSocket(this); _tcpServer = new QTcpServer(this); _tcpServer->listen(QHostAddress::Any,8888); // 服务第的ip和端口 connect(_tcpServer, &QTcpServer::newConnection, [=](){ // 有人连接时触发 _tcpSocket = _tcpServer->nextPendingConnection(); // 获取对方套接字,包含对方的基础信息 QString ip = _tcpSocket->peerAddress().toString(); // 通过套接字获取对方的iP qint16 port = _tcpSocket->peerPort(); // 通过套接字获取对方的端口 QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port); ui->textEdit->setText(temp); // 成功连接时选择文件按钮恢复 ui->pushButton->setEnabled(true); connect(_tcpSocket,&QTcpSocket::readyRead,[=](){ // 服务端收到消息 QByteArray array = _tcpSocket->readAll(); if(QString(array) == "file done"){ ui->textEdit->append("文件发送完毕"); file.close(); _tcpSocket->disconnectFromHost(); _tcpSocket->close(); } }); }); connect(&timer,&QTimer::timeout,[=](){ timer.stop();sendData(); }); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() //选择文件 { QString filePath = QFileDialog::getOpenFileName(this,"open","../"); if(filePath.isEmpty()) return; // 获取文件信息 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(!isOk) qDebug() << "只读方式打开文件失败"; ui->textEdit->append(filePath); ui->pushButton->setEnabled(false); ui->pushButton_2->setEnabled(true); // 选好了文件后,发送按钮打开 } void Widget::on_pushButton_2_clicked() // 发送文件 { // 先发送头部信息 文件名##文件大小 QString head = QString("%1##%2").arg(fileName).arg(fileSize); qint64 len = _tcpSocket->write(head.toUtf8()); if(len > 0){ // 头部信息发送成功 // 发送真正的文件数据。但为了防止TCP黏包,所以这里通过定时器延时20ms后再发送文件数据,保证头部信息发完了先 timer.start(20); }else{ qDebug() << "头部信息发送失败"; file.close(); ui->pushButton->setEnabled(true); ui->pushButton_2->setEnabled(false); } } void Widget::sendData(){ ui->textEdit->append("文件开始发送..."); qint64 len2 = 0; do{ len2 = 0; // 和len一样判断当前实际读了或者发送了多少数据 char buf[4*1024] = {0}; // 每次发送4k len2 = file.read(buf,sizeof(buf)); // 把文件数据读到buf里,读4k的内容 _tcpSocket->write(buf,len2); // 发送数据,读多少(看len2),发多少 sendSize += len2; }while(len2 > 0); // len2小于等于0了,表示没有读到数据了 // if(sendSize == fileSize){ // ui->textEdit->append("文件发送完毕"); // file.close(); // _tcpSocket->disconnectFromHost(); // _tcpSocket->close(); // } } // ----------------------- socket.h #ifndef SOCKET_H #define SOCKET_H #include <QWidget> #include <QTcpSocket> #include <QFile> namespace Ui { class socket; } class socket : public QWidget { Q_OBJECT public: explicit socket(QWidget *parent = 0); ~socket(); QTcpSocket* _tcpSocket = NULL; QFile file; QString fileName; qint64 fileSize; qint64 recvSize; bool isHead = true; private slots: void on_pushButton_clicked(); private: Ui::socket *ui; }; #endif // SOCKET_H // ----------------------- socket.cpp #include "socket.h" #include "ui_socket.h" #include <QDebug> #include <QMessageBox> #include <QHostAddress> socket::socket(QWidget *parent) : QWidget(parent), ui(new Ui::socket) { ui->setupUi(this); setWindowTitle("客户端"); ui->progressBar->setValue(0); _tcpSocket = new QTcpSocket(this); connect(_tcpSocket,&QTcpSocket::readyRead,[=](){ // 接收消息,我连接对方成功后方可接收 QByteArray array = _tcpSocket->readAll(); // 取出数据 if(isHead){ // 一开肯定是头,故isHead默认为true isHead = false; // 解析头部信息 fileName = QString(array).section("##",0,0); // section("##",0,0),以##分割成一段一段的,这里0段开始0段结束 fileSize = QString(array).section("##",1,1).toInt(); recvSize = 0; // 打开文件,根据解析得到的文件名写文件,这里执行一次即可,具体在下面写 file.setFileName(fileName); bool isOk = file.open(QIODevice::WriteOnly); if(!isOk) { qDebug() << "写文件失败"; _tcpSocket->disconnectFromHost(); _tcpSocket->close(); return; } // 弹出对话框,显示接收到了文件xinx //QString str = QString("接收的文件:[%1: %2kb]").arg(fileName).arg(fileSize/1024); //QMessageBox::information(this,"文件信息",str); // 设置进度条 ui->progressBar->setMinimum(0); //最小值 ui->progressBar->setMaximum(fileSize/1024); //最大值 ui->progressBar->setValue(0); // 当前值 }else{ // 具体信息 qint64 len = file.write(array); // 把具体信息写成文件 if(len > 0) recvSize += len; ui->progressBar->setValue(recvSize/1024); // 更新进度条 if(recvSize == fileSize){ //qDebug() << "998"; _tcpSocket->write("file done"); // 告诉服务器我接收完了 file.close(); QMessageBox::information(this,"完成","文件接收完成"); // 把接收的都写完了 _tcpSocket->disconnectFromHost(); _tcpSocket->close(); } } }); //connect(_tcpSocket,&QTcpSocket::connected,[=](){ }); } socket::~socket() { delete ui; } void socket::on_pushButton_clicked() //连接服务器 { QString ip = ui->lineEdit->text(); quint16 port = ui->lineEdit_2->text().toInt(); _tcpSocket->connectToHost(QHostAddress(ip), port); }
udp:
// ------------ widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QUdpSocket> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); QUdpSocket* udp; private: Ui::Widget *ui; }; #endif // WIDGET_H // ------------ widget.cpp #include "widget.h" #include "ui_widget.h" #include <QHostAddress> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 报文和套接字都是消息,只是协议在套接字里多放了一些东西 ui->lineEdit->setText("8888"); ui->lineEdit_2->setText("9999"); ui->lineEdit_3->setText("127.0.0.1"); udp = new QUdpSocket(this); // 创建套接字 udp->bind(ui->lineEdit->text().toInt()); // 绑定自己的端口 connect(ui->pushButton,&QPushButton::clicked,[=](){ // 发送报文(消息) udp->writeDatagram(ui->textEdit_2->toPlainText().toUtf8(),QHostAddress(ui->lineEdit_3->text()),ui->lineEdit_2->text().toInt()); ui->textEdit->append("my say: "+ui->textEdit_2->toPlainText()); ui->textEdit_2->clear(); }); connect(udp,&QUdpSocket::readyRead,[=](){ // 接收报文(消息) qint64 size = udp->pendingDatagramSize(); // 报文长度 QByteArray array = QByteArray(size,0); // 构造时初始化长度和数据 size个0 udp->readDatagram(array.data(), size); // 读到数据放到array ui->textEdit->append("to say: "+array); }); } Widget::~Widget() { delete ui; } // ------------ upd2.h #ifndef UDP2_H #define UDP2_H #include <QWidget> #include <QUdpSocket> namespace Ui { class udp2; } class udp2 : public QWidget { Q_OBJECT public: explicit udp2(QWidget *parent = 0); ~udp2(); QUdpSocket* udp; private: Ui::udp2 *ui; }; #endif // UDP2_H // ------------ upd2.cpp #include "udp2.h" #include "ui_udp2.h" udp2::udp2(QWidget *parent) : QWidget(parent), ui(new Ui::udp2) { ui->setupUi(this); // 报文和套接字都是消息,只是协议在套接字里多放了一些东西 ui->lineEdit->setText("9999"); ui->lineEdit_2->setText("8888"); ui->lineEdit_3->setText("127.0.0.1"); udp = new QUdpSocket(this); // 创建套接字 udp->bind(ui->lineEdit->text().toInt()); // 绑定自己的端口 connect(ui->pushButton,&QPushButton::clicked,[=](){ // 发送报文(消息) udp->writeDatagram(ui->textEdit_2->toPlainText().toUtf8(),QHostAddress(ui->lineEdit_3->text()),ui->lineEdit_2->text().toInt()); ui->textEdit->append("my say:"+ui->textEdit_2->toPlainText()); ui->textEdit_2->clear(); }); connect(udp,&QUdpSocket::readyRead,[=](){ // 接收报文(消息) qint64 size = udp->pendingDatagramSize(); // 报文长度 QByteArray array = QByteArray(size,0); // 构造时初始化长度和数据 size个0 udp->readDatagram(array.data(), size); // 读到数据放到array ui->textEdit->append("to say: "+array); }); } udp2::~udp2() { delete ui; }
本文来自博客园,作者:封兴旺,转载请注明原文链接:https://www.cnblogs.com/fxw1/p/16633479.html