服务器:
.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:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
void on_newConnection_slot(); //给信号声明槽函数
void on_readyread_solt();
void send(QString mes);//自定义广播函数
private:
Ui::Widget *ui;
QTcpServer * server;
QList<QTcpSocket * >socketlist;
};
#endif // WIDGET_H
.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_pushButton_clicked()
{
quint16 port =quint16(ui->portEdit->text().toUInt());
//将服务器设置为监听
bool lis;
if(server->listen(QHostAddress::Any,port))
{
//将相应的控件设置为不可用状态
ui->pushButton->setEnabled(false);
ui->portEdit->setEnabled(false);
//新客户端连接时发送信号
connect(server,&QTcpServer::newConnection,this,&Widget::on_newConnection_slot);
}
}
//槽函数定义
void Widget::on_newConnection_slot()
{
//获取新客户端连接的套接字
QTcpSocket * socket = server->nextPendingConnection();
//将新套接字放入套接字列表中
socketlist.append(socket);
//当服务器接收到传来的消息时接收到readyRead信号
connect(socket, &QTcpSocket::readyRead , this, &Widget::on_readyread_solt);
}
void Widget::on_readyread_solt()
{
for(qint16 i=0;i<socketlist.count();i++)
{
if(socketlist.at(i)->state()==false)
{
socketlist.removeAt(i);
}
}
//遍历客户端列表找到那个客户端发送消息
for(qint16 i=0;i<socketlist.count();i++)
{
//获取客户端中代读数据个数
if(socketlist.at(i)->bytesAvailable()!=0)
{
//获取客户端传输的代读数据
QString mes = QString::fromLocal8Bit( socketlist.at(i)->readAll());
ui->listWidget->addItem(mes);
//并将该消息进行广播
send(mes);
}
}
}
//广播函数
void Widget::send(QString mes)
{
for(qint16 i=0;i<socketlist.count();i++)
{
socketlist.at(i)->write(mes.toLocal8Bit());
}
}
客户端:
.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
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_sendbtn_clicked();
void on_btn_clicked();
void on_connection_slot();
void on_disconnection_slot();
void on_readyread_solt();
private:
Ui::Widget *ui;
QTcpSocket *socket; //客户端套接字
QString uname;
bool isok;
};
#endif // WIDGET_H
.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
isok = false;
connect(socket,&QTcpSocket::connected,this,&Widget::on_connection_slot);
connect(socket,&QTcpSocket::disconnected,this,&Widget::on_disconnection_slot);
connect(socket, &QTcpSocket::readyRead , this, &Widget::on_readyread_solt);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_sendbtn_clicked()
{
QString mes = uname + ":" + ui->textEdit->text();
socket->write(mes.toLocal8Bit());
mes.clear();
}
void Widget::on_btn_clicked()
{
QString ip = ui->ipEdit->text();
quint16 port = quint16(ui->portEdit->text().toInt());
if(isok==false)
{
//连接
socket->connectToHost(QHostAddress(ip),port);
//按钮文本改完断开
ui->btn->setText("断开");
isok=true;
}else
{
//断开服务器
socket->disconnectFromHost();
//更改按钮文本
ui->btn->setText("连接");
isok=false;
}
}
void Widget::on_connection_slot()
{
uname = ui->nameEdit->text();
QString mes = uname + "加入群聊";
ui->listWidget->addItem(mes);
socket->write(mes.toLocal8Bit());
// mes.clear();
ui->portEdit->setEnabled(false);
ui->ipEdit->setEnabled(false);
ui->nameEdit->setEnabled(false);
}
void Widget::on_disconnection_slot()
{
QString mes = uname + "离开群聊";
ui->listWidget->addItem(mes);
socket->write(mes.toLocal8Bit());
// mes.clear();
ui->portEdit->setEnabled(true);
ui->ipEdit->setEnabled(true);
ui->nameEdit->setEnabled(true);
}
void Widget::on_readyread_solt()
{
QString mes = QString::fromLocal8Bit(socket->readAll());
ui->listWidget->addItem(mes);
}