本次搭建需要使用关于TCP的库,所以需要在配置文件中加入
QT += network
一、服务器的搭建
1、ui界面的构建
2、widget.h
主要是头文件的包络和函数的声明
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_startBtn_clicked();
void on_newConnection_slot();
void on_readyRead_slot();
void send(QString mes);
private:
Ui::Widget *ui;
//定义一个服务器指针
QTcpServer *server;
//定义一个客户端指针,存放连接的客户端
QList<QTcpSocket *> socketList;
};
#endif // WIDGET_H
3、widget.cpp
主要是对于函数的定义与服务器的实例化,对客户端连接时和断开连接时发出的信号进行处理并实现相应功能
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//实例化服务器
server = new QTcpServer(this);
}
Widget::~Widget()
{
delete ui;
}
//启动按钮对应的槽函数
void Widget::on_startBtn_clicked()
{
quint16 port = quint16(ui->portEdit->text().toInt());
//将服务器设置为监听状态
server->listen(QHostAddress::Any,port);
//将相应的控件设置为不可用状态
ui->portEdit->setEnabled(false);
ui->startBtn->setEnabled(false);
//当有新的客户端连接到该服务器后,会出现
connect(server,&QTcpServer::newConnection,this,&Widget::on_newConnection_slot);
}
void Widget::on_newConnection_slot()
{
QTcpSocket * socket = server->nextPendingConnection();
//将该套接字放入套接字链表中
socketList.append(socket);
//当服务器接收到客户端传过来的消息时,
connect(socket, &QTcpSocket::readyRead, this, &Widget::on_readyRead_slot);
}
void Widget::on_readyRead_slot()
{
//判断客户端套接字是否有效,如果无效则移除
for(int i=0; i<socketList.count(); i++)
{
if(socketList.at(i)->state() == false)
{
socketList.removeAt(i);
}
}
//遍历客户端的链表,判断是哪一个客户端发送消息
for(quint16 j=0; j<socketList.count() ;j++)
{
if(socketList.at(j)->bytesAvailable())
{
QString mes = QString::fromLocal8Bit( socketList.at(j)->readAll());
//将消息展示到list widget上
ui->listWidget->addItem(mes);
//同时还要把该消息进行广播
send(mes);
}
}
}
二、客户端的搭建
1、ui界面的构建

2、widget.h
主要是头文件的包络和函数的声明
#ifndef CHATCLIENT_H
#define CHATCLIENT_H
#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
QT_BEGIN_NAMESPACE
namespace Ui { class chatClient; }
QT_END_NAMESPACE
class chatClient : public QWidget
{
Q_OBJECT
public:
chatClient(QWidget *parent = nullptr);
~chatClient();
private slots:
void on_connectBtn_clicked();
void on_connected_slot();
void on_disconnected_slot();
void on_readyRead_slot();
void on_sendBtn_clicked();
private:
Ui::chatClient *ui;
//定义客户端套接字指针
QTcpSocket *socket;
//定义用户名;
QString usename;
//定义bool类型数据,表示连接状态
bool isok;
};
#endif // CHATCLIENT_H
3、widget.cpp
主要是对于函数的定义与服务器的实例化,对客户端连接时和断开连接时发出的信号进行处理并实现相应功能
#include "chatclient.h"
#include "ui_chatclient.h"
#include <QHostAddress>
chatClient::chatClient(QWidget *parent)
: QWidget(parent)
, ui(new Ui::chatClient)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
//给连接状态初始值
isok =false;
//将connect信号连接到自定义的槽函数
connect(socket,&QTcpSocket::connected,this,&chatClient::on_connected_slot);
//将disconnect信号连接到自定义的槽函数
connect(socket,&QTcpSocket::disconnected,this,&chatClient::on_disconnected_slot);
//
connect(socket,&QTcpSocket::readyRead,this,&chatClient::on_readyRead_slot);
}
chatClient::~chatClient()
{
delete ui;
}
void chatClient::on_connectBtn_clicked()
{
QString ip = ui->ipEdit->text();
quint16 port = ui->porEdit->text().toInt();
//判断连接状态
if(isok == false)
{
//连接服务器
socket->connectToHost(QHostAddress(ip),port);
//将按钮文本改为"断开连接"
ui->connectBtn->setText("断开连接");
isok = true;
//将相应的控件设置为不可用状态
ui->ipEdit->setEnabled(false);
ui->porEdit->setEnabled(false);
ui->userEdit->setEnabled(false);
}else
{
usename = ui->userEdit->text();
QString mes = usename + "离开群聊";
socket->write(mes.toLocal8Bit());
//断开服务器
socket->disconnectFromHost();
ui->connectBtn->setText("连接服务器");
isok = false;
//将相应的控件恢复为可用状态
ui->ipEdit->setEnabled(true);
ui->porEdit->setEnabled(true);
ui->userEdit->setEnabled(true);
}
}
void chatClient::on_connected_slot()
{
usename = ui->userEdit->text();
QString mes = usename + "加入群聊";
socket->write(mes.toLocal8Bit());
}
void chatClient::on_disconnected_slot()
{
}
//readyRead信号对应的槽函数的定义
void chatClient::on_readyRead_slot()
{
//获取套接字中的数据
QString mes = QString::fromLocal8Bit(socket->readAll());
ui->listWidget->addItem(mes);
}
void chatClient::on_sendBtn_clicked()
{
usename = ui->userEdit->text();
QString mes = usename + ":" + ui->mesEdit->text();
socket->write(mes.toLocal8Bit());
ui->mesEdit->clear();
}
本文档详细介绍了如何使用QT库构建基于TCP的服务器和客户端。首先,服务器的搭建包括UI界面构建,以及在widget.h和widget.cpp中声明和定义相关函数,处理客户端连接和断开的信号。接着,客户端的搭建同样涉及UI界面,以及在相应的头文件和源文件中进行函数定义和服务器实例化,处理连接状态变化。

3084

被折叠的 条评论
为什么被折叠?



