服务器端:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDialog>
class QTcpServer;
class MainWindow : public QDialog
{
Q_OBJECT
public:
MainWindow(QDialog *parent = nullptr);
~MainWindow();
private slots:
void sendMessage();
private:
QTcpServer *tcp_server_;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QtNetwork>
MainWindow::MainWindow(QDialog *parent)
: QDialog(parent)
{
tcp_server_ = new QTcpServer(this);
//监听IP地址及端口号到来的连接
//使用了IPv4的本地主机地址,等价于QHostAddress("127.0.0.1")
if(!tcp_server_->listen(QHostAddress::LocalHost, 6666)){
qDebug() << tcp_server_->errorString();
close();
}
//一旦有客户端连接到服务器,则发射newConnection信号
connect(tcp_server_, &QTcpServer::newConnection, this, &MainWindow::sendMessage);
}
MainWindow::~MainWindow()
{
}
void MainWindow::sendMessage()
{
//用于暂存要发送的数据
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);;//用于序列化和反序列化
//设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_5_6);
out <<(quint16)0;//保留两个字节的位置,以便以后填写数据大小信息
out << tr("hello TCP!!");//使用tr进行编码
out.device()->seek(0);//跳转到数据开头
out << (quint16)(block.size()-sizeof(quint16));
//获取已经建立的连接的套接字
QTcpSocket *client_connection = tcp_server_->nextPendingConnection();
//连接断开时,删除套接字
connect(client_connection, &QTcpSocket::disconnected, client_connection, &QTcpSocket::deleteLater);
client_connection->write(block);
client_connection->disconnectFromHost();//一直等待套接字将所有数据发送完毕,然后关闭该套接字,并发送disconnected信号
//发送数据成功后,显示提示
qDebug() << QString::fromLocal8Bit("发送数据成功");
}
客户端:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QAbstractSocket>
class QTcpSocket;
class QLabel;
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void newConnect();
void readMessage();
void displayError(QAbstractSocket::SocketError);
private:
QTcpSocket *tcp_socket_;
QString message;
//用来存放数据的大小信息
quint16 block_size_;
QLabel *label;
};
#endif // DIALOG_H
#include "dialog.h"
#include <QtNetwork>
#include <QLabel>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
label = new QLabel(this);
label->setGeometry(0,0,200,20);
tcp_socket_ = new QTcpSocket(this);
//有数据可读时发送readyread信号
connect(tcp_socket_, &QTcpSocket::readyRead, this, &Dialog::readMessage);
//发生错误时,发送error信号
connect(tcp_socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
newConnect();
}
Dialog::~Dialog()
{
}
void Dialog::newConnect()
{
//初始化数据大小信息为0
block_size_ = 0;
//取消当前存在连接,并重置套接字
tcp_socket_->abort();
//连接到指定主机的指定端口
tcp_socket_->connectToHost(QHostAddress::LocalHost, 6666);
}
void Dialog::readMessage()
{
QDataStream in(tcp_socket_);
//设置数据流版本,这里要和服务器端相同
in.setVersion(QDataStream::Qt_5_6);
if(block_size_ == 0){
//判断接受的数据是否大于两字节,也就是文件的大小信息所占的空间
//如果是则保存到block_size_变量中,否则直接返回,继续接受数据
if(tcp_socket_->bytesAvailable() < sizeof(quint16)){
return;
}
in >> block_size_;
}
//如果没有得到全部的数据,则返回,继续接收数据
if(tcp_socket_->bytesAvailable() < block_size_){
return;
}
in >> message;
//处理数据
qDebug() << message;
label->setText(message);
}
void Dialog::displayError(QAbstractSocket::SocketError)
{
//输出错误信息
qDebug() << tcp_socket_->errorString();
}