我是靠谱客的博主 平常钢笔,最近开发中收集的这篇文章主要介绍Qt网络编程——TCP1. 概念2. 服务器3. 客户端4. TCP服务器和客户端互传文件5. 资源下载,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
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_OBJECT
public:
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_OBJECT
public:
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_OBJECT
public:
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; // 64KB
totalBytes = 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);
// 初始化已发送字节为0
bytesWritten = 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_OBJECT
public:
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网络编程——TCP1. 概念2. 服务器3. 客户端4. TCP服务器和客户端互传文件5. 资源下载的全部内容,希望文章能够帮你解决Qt网络编程——TCP1. 概念2. 服务器3. 客户端4. TCP服务器和客户端互传文件5. 资源下载所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复