Qt网络编程——TCP

  • 1. 概念
  • 2. 服务器
  • 3. 客户端
  • 4. TCP服务器和客户端互传文件
  • 5. 资源下载

1. 概念

  • TCP(Transmission Control Protocol, 传输控制协议) 是一个用于数据传输的底层网络协议。
  • TCP 是一个面向数据流和连接的可靠的传输协议。

2. 服务器

  • tcpserver.pro
QT       += network
  • server.h
#ifndef SERVER_H
#define SERVER_H#include <QDialog>class QTcpServer;namespace Ui {class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent = 0);~Server();private:Ui::Server *ui;QTcpServer * tcpServer;private slots:void sendMessage();
};#endif // SERVER_H
  • server.cpp
#include "server.h"
#include "ui_server.h"
#include <QtNetwork>
#include <QDebug>Server::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui->setupUi(this);tcpServer = new QTcpServer(this);//监听连接//使用了IPv4的本地主机地址,等价于 QHostAddress("127.0.0.1")if(!tcpServer->listen(QHostAddress::LocalHost,6666)){qDebug()<<tcpServer->errorString();close();}connect(tcpServer,&QTcpServer::newConnection,this,&Server::sendMessage);
}Server::~Server()
{delete ui;
}void Server::sendMessage()
{//用于暂存要发送的数据QByteArray block;QDataStream out(&block,QIODevice::WriteOnly);//设置数据流的版本,客户端和服务器端使用的版本要相同out.setVersion(QDataStream::Qt_5_6);out<<(quint16)0;out<<tr("HelloTCP!");//跳转到数据块开头,然后将获取的大小信息填写到前面空留的两个字节处out.device()->seek(0);out<<(quint16)(block.size()-sizeof(quint16));//获取已经建立的连接的套接字QTcpSocket * clientConnection = tcpServer->nextPendingConnection();connect(clientConnection,&QTcpSocket::disconnected,clientConnection,&QTcpSocket::deleteLater);//发送数据clientConnection->write(block);clientConnection->disconnectFromHost();ui->label->setText(tr("发送数据成功"));
}

3. 客户端

  • tcpclient.pro
QT       += network
  • client.h
#ifndef CLIENT_H
#define CLIENT_H#include <QDialog>
#include <QAbstractSocket>class QTcpSocket;
namespace Ui {class Client;
}class Client : public QDialog
{Q_OBJECTpublic:explicit Client(QWidget *parent = 0);~Client();private:Ui::Client *ui;QTcpSocket * tcpSocket;QString message;//存放数据的大小信息quint16 blockSize;private slots:void newConnect();void readMessage();void displayError(QAbstractSocket::SocketError);  void on_pushButtonConnect_clicked();
};#endif // CLIENT_H
  • client.cpp
#include "client.h"
#include "ui_client.h"
#include <QtNetwork>Client::Client(QWidget *parent) :QDialog(parent),ui(new Ui::Client)
{ui->setupUi(this);tcpSocket = new QTcpSocket(this);//这里关联了两个信号到自定义槽上,当有可读的数据时,会发射readyRead()信号//当发生错误时,会发射error()信号connect(tcpSocket,&QTcpSocket::readyRead,this,&Client::readMessage);connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
}Client::~Client()
{delete ui;
}void Client::newConnect()
{blockSize = 0;tcpSocket->abort();tcpSocket->connectToHost(ui->lineEditHost->text(),ui->lineEditPort->text().toInt());
}void Client::readMessage()
{QDataStream in(tcpSocket);//设置数据流版本,这里要和服务器端相同in.setVersion(QDataStream::Qt_5_6);//如果是刚开始接收数据if(blockSize == 0){//判断接受的数据是否大于两字节,也就是文件的大小信息所占的空间//如果是则保存到blockSize变量中,否则直接返回,继续接收数据if(tcpSocket->bytesAvailable()<(int)sizeof(quint16))return;in>>blockSize;}//如果没有得到全部的数据,则返回,继续接收数据if(tcpSocket->bytesAvailable()<blockSize)return;//将接受到的数据放到变量中in>>message;//显示接收到的数据ui->labelMessage->setText(message);
}void Client::displayError(QAbstractSocket::SocketError)
{qDebug()<<tcpSocket->errorString();
}void Client::on_pushButtonConnect_clicked()
{newConnect();
}

4. TCP服务器和客户端互传文件

  • client.h
#ifndef CLIENT_H
#define CLIENT_H#include <QDialog>
#include <QAbstractSocket>
class QTcpSocket;
class QFile;namespace Ui {class Client;
}class Client : public QDialog
{Q_OBJECTpublic:explicit Client(QWidget *parent = 0);~Client();private:Ui::Client *ui;QTcpSocket *tcpClient;QFile *localFile;     // 要发送的文件qint64 totalBytes;    // 发送数据的总大小qint64 bytesWritten;  // 已经发送数据大小qint64 bytesToWrite;  // 剩余数据大小qint64 payloadSize;   // 每次发送数据的大小QString fileName;     // 保存文件路径QByteArray outBlock;  // 数据缓冲区,即存放每次要发送的数据块private slots:void openFile();void send();void startTransfer();void updateClientProgress(qint64);void displayError(QAbstractSocket::SocketError);void on_openButton_clicked();void on_sendButton_clicked();
};#endif // CLIENT_H
  • client.cpp
#include "client.h"
#include "ui_client.h"
#include <QtNetwork>
#include <QFileDialog>Client::Client(QWidget *parent) :QDialog(parent),ui(new Ui::Client)
{ui->setupUi(this);payloadSize = 64*1024; // 64KBtotalBytes = 0;bytesWritten = 0;bytesToWrite = 0;tcpClient = new QTcpSocket(this);// 当连接服务器成功时,发出connected()信号,开始传送文件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)));ui->sendButton->setEnabled(false);
}Client::~Client()
{delete ui;
}void Client::openFile()
{fileName = QFileDialog::getOpenFileName(this);if (!fileName.isEmpty()) {ui->sendButton->setEnabled(true);ui->clientStatusLabel->setText(tr("打开文件 %1 成功!").arg(fileName));}
}void Client::send()
{ui->sendButton->setEnabled(false);// 初始化已发送字节为0bytesWritten = 0;ui->clientStatusLabel->setText(tr("连接中…"));tcpClient->connectToHost(ui->hostLineEdit->text(),ui->portLineEdit->text().toInt());
}void Client::startTransfer()
{localFile = new QFile(fileName);if (!localFile->open(QFile::ReadOnly)) {qDebug() << "client: open file error!";return;}// 获取文件大小totalBytes = localFile->size();QDataStream sendOut(&outBlock, QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_4_0);QString currentFileName = fileName.right(fileName.size()- fileName.lastIndexOf('/')-1);// 保留总大小信息空间、文件名大小信息空间,然后输入文件名sendOut << qint64(0) << qint64(0) << currentFileName;// 这里的总大小是总大小信息、文件名大小信息、文件名和实际文件大小的总和totalBytes += outBlock.size();sendOut.device()->seek(0);// 返回outBolock的开始,用实际的大小信息代替两个qint64(0)空间sendOut << totalBytes << qint64((outBlock.size() - sizeof(qint64)*2));// 发送完文件头结构后剩余数据的大小bytesToWrite = totalBytes - tcpClient->write(outBlock);ui->clientStatusLabel->setText(tr("已连接"));outBlock.resize(0);
}void Client::updateClientProgress(qint64 numBytes)
{// 已经发送数据的大小bytesWritten += (int)numBytes;// 如果已经发送了数据if (bytesToWrite > 0) {// 每次发送payloadSize大小的数据,这里设置为64KB,如果剩余的数据不足64KB,// 就发送剩余数据的大小outBlock = localFile->read(qMin(bytesToWrite, payloadSize));// 发送完一次数据后还剩余数据的大小bytesToWrite -= (int)tcpClient->write(outBlock);// 清空发送缓冲区outBlock.resize(0);} else { // 如果没有发送任何数据,则关闭文件localFile->close();}// 更新进度条ui->clientProgressBar->setMaximum(totalBytes);ui->clientProgressBar->setValue(bytesWritten);// 如果发送完毕if(bytesWritten == totalBytes) {ui->clientStatusLabel->setText(tr("传送文件 %1 成功").arg(fileName));localFile->close();tcpClient->close();}
}void Client::displayError(QAbstractSocket::SocketError)
{qDebug() << tcpClient->errorString();tcpClient->close();ui->clientProgressBar->reset();ui->clientStatusLabel->setText(tr("客户端就绪"));ui->sendButton->setEnabled(true);
}// 打开按钮
void Client::on_openButton_clicked()
{ui->clientProgressBar->reset();ui->clientStatusLabel->setText(tr("状态:等待打开文件!"));openFile();}// 发送按钮
void Client::on_sendButton_clicked()
{send();
}
  • server.h
#ifndef SERVER_H
#define SERVER_H#include <QDialog>
#include <QAbstractSocket>
#include <QTcpServer>
class QTcpSocket;
class QFile;namespace Ui {class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent = 0);~Server();private:Ui::Server *ui;QTcpServer tcpServer;QTcpSocket *tcpServerConnection;qint64 totalBytes;     // 存放总大小信息qint64 bytesReceived;  // 已收到数据的大小qint64 fileNameSize;   // 文件名的大小信息QString fileName;      // 存放文件名QFile *localFile;      // 本地文件QByteArray inBlock;    // 数据缓冲区private slots:void start();void acceptConnection();void updateServerProgress();void displayError(QAbstractSocket::SocketError socketError);void on_startButton_clicked();
};#endif // SERVER_H
  • server.cpp
#include "server.h"
#include "ui_server.h"
#include <QtNetwork>Server::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui->setupUi(this);connect(&tcpServer, SIGNAL(newConnection()),this, SLOT(acceptConnection()));}Server::~Server()
{delete ui;
}void Server::start()
{if (!tcpServer.listen(QHostAddress::LocalHost, 6666)) {qDebug() << tcpServer.errorString();close();return;}ui->startButton->setEnabled(false);totalBytes = 0;bytesReceived = 0;fileNameSize = 0;ui->serverStatusLabel->setText(tr("监听"));ui->serverProgressBar->reset();
}void Server::acceptConnection()
{tcpServerConnection = tcpServer.nextPendingConnection();connect(tcpServerConnection, SIGNAL(readyRead()),this, SLOT(updateServerProgress()));connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(displayError(QAbstractSocket::SocketError)));ui->serverStatusLabel->setText(tr("接受连接"));// 关闭服务器,不再进行监听tcpServer.close();
}void Server::updateServerProgress()
{QDataStream in(tcpServerConnection);in.setVersion(QDataStream::Qt_4_0);// 如果接收到的数据小于16个字节,保存到来的文件头结构if (bytesReceived <= sizeof(qint64)*2) {if((tcpServerConnection->bytesAvailable() >= sizeof(qint64)*2)&& (fileNameSize == 0)) {// 接收数据总大小信息和文件名大小信息in >> totalBytes >> fileNameSize;bytesReceived += sizeof(qint64) * 2;}if((tcpServerConnection->bytesAvailable() >= fileNameSize)&& (fileNameSize != 0)) {// 接收文件名,并建立文件in >> fileName;ui->serverStatusLabel->setText(tr("接收文件 %1 …").arg(fileName));bytesReceived += fileNameSize;localFile = new QFile(fileName);if (!localFile->open(QFile::WriteOnly)) {qDebug() << "server: open file error!";return;}} else {return;}}// 如果接收的数据小于总数据,那么写入文件if (bytesReceived < totalBytes) {bytesReceived += tcpServerConnection->bytesAvailable();inBlock = tcpServerConnection->readAll();localFile->write(inBlock);inBlock.resize(0);}ui->serverProgressBar->setMaximum(totalBytes);ui->serverProgressBar->setValue(bytesReceived);// 接收数据完成时if (bytesReceived == totalBytes) {tcpServerConnection->close();localFile->close();ui->startButton->setEnabled(true);ui->serverStatusLabel->setText(tr("接收文件 %1 成功!").arg(fileName));}
}void Server::displayError(QAbstractSocket::SocketError socketError)
{qDebug() << tcpServerConnection->errorString();tcpServerConnection->close();ui->serverProgressBar->reset();ui->serverStatusLabel->setText(tr("服务端就绪"));ui->startButton->setEnabled(true);
}// 开始监听按钮
void Server::on_startButton_clicked()
{start();
}

5. 资源下载

https://download.csdn.net/download/weixin_38566632/85187690

Qt网络编程——TCP相关推荐

  1. qt android 网络编程实例,QT网络编程Tcp下C/S架构的即时通信实例

    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include #include # ...

  2. QT网络编程——TCP服务器和客户端通信

    目录 一.服务器端 1.QT中TCP服务器的开发思路 2.QT服务器界面设计 3.QT服务器代码实现 二.客户端 1.QT中TCP客户端的开发思路 2.QT客户端界面设计 3.QT客户端代码实现 网络 ...

  3. Qt网络编程——TCP服务器与客户端互发信息

    前言 前一个博客,试了TCP的服务器与客户端的连接与断开,接下就是客户端与服务器互发信息. 客户端 1.往服务器发送信息 //发送消息 void Client::on_buttonSendMessag ...

  4. QT入门第七天 网络编程TCP/IP/UDP+Http和JSON解析+qt事件软键盘【CSDN最详细】

    网络编程+Http和JSON解析+qt事件软键盘 第一章 QT中的网络编程 [1]涉及到的类 [2]tcp协议的流程 [2.1]服务器的流程 socket-->bind-->listen- ...

  5. Qt:Qt实现Winsock网络编程—TCP服务端和客户端通信(多线程)

    Qt实现Winsock网络编程-TCP服务端和客户端通信(多线程) 前言 感觉Winsock网络编程的api其实和Linux下网络编程的api非常像,其实和其他编程语言的网络编程都差不太多.博主用Qt ...

  6. Qt网络编程电子白板

    Qt网络编程电子白板 2018-08-11 08:44:04 天行健_地势坤 阅读数 915更多 分类专栏: Qt 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  7. 第十四章:Qt网络编程

    回顾: 第一章:Qt的概述 第二章:在Ubuntu编写第一个Qt程序 第三章:Qt的字符串和字符编码 第四章:Qt的信号和槽 第五章:Qt容器窗口(父窗口) 第六章:面向对象的Qt编程 第七章:Qt设 ...

  8. Qt网络编程概述(一)

    分享主题 Qt网络编程概述(一) Qt网络编程之QTCPSocket和QTCPServer实例(二) Qt网络编程之QUdpSocket实例(三) Qt网络编程概述 QtNetWork模块提供了若干类 ...

  9. QT网络编程开发服务端

    下一篇: QT网络编程开发客户端 文章目录 基于Qt的网络编程服务端 QTcpServer 配置 listen() close() newConnection() SINGL readyRead() ...

最新文章

  1. springboot-mysql-pagehelper分页插件集成
  2. CoreOS集成Kubernetes核心组件Kubelet
  3. 让 Windows 7 定时待机
  4. 2.3 Factory Method(工厂方法)
  5. WIFI断网: 802.11协议Deauthentication Reason Codes
  6. 【图像隐写】基于matlab DWT数字水印多种攻击效果对比【含Matlab源码 1134期】
  7. 【IT】QTTabBar使用
  8. 航拍南山区六个文化相关全景VR解读
  9. 若依RuoYi-Vue 入门零接触超详细(一)
  10. ipad pro + zotero + 坚果云 + PDF Expert 搭建多平台文献管理(自用备忘)
  11. 自定义竖向SeekBar (VerticalSeekBar)
  12. 漏损分析与控制技术——漏损分析技术
  13. 磁盘最优存储问题---Python
  14. java 距离转坐标_Java经纬读坐标的距离计算
  15. iOS开发 - ANPs推送通知
  16. 计算机控制技术直流电机调速控制实验报告,pid直流电机转速控制实验报告(31页)-原创力文档...
  17. FBI指控SamSam勒索软件幕后黑手
  18. Windows平台如何快速打开体积大的txt等文本文件
  19. 如何在canvas画布上自定义鼠标右键菜单内容?
  20. java开发环境搭建——mysql、navicat、powerDesigner下载安装

热门文章

  1. 惠普台式机重装系统之后,无法进入系统
  2. Nginx端口映射(外网访问)
  3. php 检测 变量是否设置,php如何判断变量是否有设置的函数
  4. Tomcat不能自动编译JSP文件问题的一种解决方法
  5. iframe中src参数过长问题解决
  6. DB2报“数据库日志已满”问题解决
  7. linux 出现 -bash-4.2# 问题的解决方法
  8. JS传值中文乱码解决方案
  9. 接口返回[object,Object]解决方法
  10. tomcat端口被占用问题完美解决方案!