云计算百科
云计算领域专业知识百科平台

QT TCP服务器/客户端【多线程】

服务器

文件结构 首先要在.pro文件中添加network,否则将不能使用QTcpserver

QT += core gui network

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#define PORT 8000

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void newClientHandler();
void clientInfoSlot();

void on_sendButton_clicked();

private:
Ui::Widget *ui;
QTcpServer *server;
QTcpSocket *socket;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
server = new QTcpServer;
//开启端口监视(服务)
server->listen(QHostAddress::AnyIPv4,PORT);
//将Server的新连接信号,绑定newClientHandler槽函数
connect(server,&QTcpServer::newConnection,this,&Widget::newClientHandler);
}

Widget::~Widget()
{
delete ui;
}
void Widget::newClientHandler()
{
//建立TCP连接,sever
socket = server->nextPendingConnection();
ui->addresslineEdit->setText(socket->peerAddress().toString());
ui->portlineEdit->setText(QString::number(socket->peerPort()));
//将Socket的数据就绪信号,绑定clientInfoSlot槽函数
connect(socket,&QTcpSocket::readyRead,this,&Widget::clientInfoSlot);

}
void Widget::clientInfoSlot()
{
//获取信号的发出者
QTcpSocket *socket=(QTcpSocket *)sender();
ui->revlineEdit->setText(QString(socket->readAll()));
}

void Widget::on_sendButton_clicked()
{
QByteArray ba;
ba.append(ui->sendlineEdit->text().toLatin1());
socket->write(ba);
}

在这里插入图片描述

客户端

在这里插入图片描述 同样的,别忘了在.pro文件中修改

QT += core gui network

客户端建立连接之后开启新窗口chat

#ifndef CHAT_H
#define CHAT_H

#include <QWidget>
#include<QTcpSocket>
namespace Ui {
class chat;
}

class chat : public QWidget
{
Q_OBJECT

public:
explicit chat(QTcpSocket *socket,QWidget *parent = nullptr);
~chat();

private slots:
void on_sendButton_clicked();

void on_clearButton_clicked();

void clientReadHandler();

private:
Ui::chat *ui;
QTcpSocket *socket;
};

#endif // CHAT_H

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpsocket>
#include<QHostAddress>
#include<QMessageBox>
#include "chat.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void on_cancelButton_clicked();

void on_connectButton_clicked();

private:
Ui::Widget *ui;
QTcpSocket *socket;
chat *ch;
};
#endif // WIDGET_H

#include "chat.h"
#include "ui_chat.h"

chat::chat(QTcpSocket *s,QWidget *parent) :
QWidget(parent),
ui(new Ui::chat)
{
ui->setupUi(this);
socket = s;
connect(socket,&QTcpSocket::readyRead,this,&chat::clientReadHandler);
}

chat::~chat()
{
delete ui;
}

void chat::on_sendButton_clicked()
{
QByteArray ba;
ba.append(ui->lineEdit->text().toLatin1());
socket->write(ba);
}

void chat::on_clearButton_clicked()
{
ui->lineEdit->clear();
}

void chat::clientReadHandler()
{
ui->revlineEdit->setText(QString(socket->readAll()));
}

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
socket = new QTcpSocket;
}

Widget::~Widget()
{
delete ui;
}

void Widget::on_connectButton_clicked()
{
QString ip = ui->iplineEdit->text();
QString port = ui->portlineEdit->text();
qDebug() << ip;
qDebug() << port;

socket->connectToHost(QHostAddress(ip),port.toShort());
//绑定QTcpSocket::connected信号
connect(socket,&QTcpSocket::connected,[this]{
QMessageBox::information(this,"Tip","连接成功");
this->hide();
//开启新窗口,将socket作为参数。
ch = new chat(socket);
ch->show();
});
connect(socket,&QTcpSocket::disconnected,[this]{
QMessageBox::information(this,"Tip","连接失败!");
});
}

void Widget::on_cancelButton_clicked()
{
this->close();
}

在这里插入图片描述 在这里插入图片描述

多线程版本【针对服务端】

当存在多个客户端连接服务端的时候,如果只用一个线程,会造成先启动的客户端无法读写。此时,需要服务端开启多线程服务。 在这里插入图片描述 在这里插入图片描述

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>
#include<QTcpSocket>
#include<QDebug>

class myThread : public QThread
{
Q_OBJECT
public:
explicit myThread(QTcpSocket *socket);
void run();
signals:
void sentToWidget(QByteArray *b);
private slots:
void clientinfoSolt();
private:
QTcpSocket *socket;
QByteArray *ba;
};

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include"mythread.h"

#define PORT 8000

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void newClientHandler();
void clientInfoSlot();

void on_sendButton_clicked();
void threadSlot(QByteArray *b);
private:
Ui::Widget *ui;
QTcpServer *server;
QTcpSocket *socket;
};
#endif // WIDGET_H

#include "mythread.h"

myThread::myThread(QTcpSocket *s)
:socket{s}
{
ba = new QByteArray;
}
void myThread::run()
{
Qt::HANDLE hd = QThread::currentThreadId();
QString hdstr = QString::number(reinterpret_cast<quintptr>(hd));
qDebug()<<"线程:";
qDebug()<<hdstr;
ba->append("th ID:");
ba->append(hdstr.toUtf8());
connect(socket,&QTcpSocket::readyRead,this,&myThread::clientinfoSolt);
}
void myThread::clientinfoSolt()
{
//qDebug()<<socket->readAll();
ba->append(socket->readAll());
emit sentToWidget(ba);//发送信号
}

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
server = new QTcpServer;
server->listen(QHostAddress::AnyIPv4,PORT);
connect(server,&QTcpServer::newConnection,this,&Widget::newClientHandler);
}

Widget::~Widget()
{
delete ui;
}
void Widget::newClientHandler()
{
//建立TCP连接
socket = server->nextPendingConnection();
ui->addresslineEdit->setText(socket->peerAddress().toString());
ui->portlineEdit->setText(QString::number(socket->peerPort()));
connect(socket,&QTcpSocket::readyRead,this,&Widget::clientInfoSlot);
//启动线程
myThread *t = new myThread(socket);//创建线程对象
t->start();

connect(t,&myThread::sentToWidget,this,&Widget::threadSlot);
}
void Widget::threadSlot(QByteArray *b)
{
ui->revlineEdit->append(QString(*b));
}

void Widget::clientInfoSlot()
{
//获取信号的发出者
QTcpSocket *socket=(QTcpSocket *)sender();
//ui->revlineEdit->setText(QString(socket->readAll()));
ui->revlineEdit->append(QString(socket->readAll()));
}

void Widget::on_sendButton_clicked()
{
QByteArray ba;
ba.append(ui->sendlineEdit->text().toLatin1());
socket->write(ba);
}

赞(0)
未经允许不得转载:网硕互联帮助中心 » QT TCP服务器/客户端【多线程】
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!