服务端:
chartser.h:
#ifndef CHATSER1_H
#define CHATSER1_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>
QT_BEGIN_NAMESPACE
namespace Ui { class chatser1; }
QT_END_NAMESPACE
class chatser1 : public QWidget
{
Q_OBJECT
public:
chatser1(QWidget *parent = nullptr);
~chatser1();
private slots:
void on_startBtn_clicked();
void on_newConnection_slot();
void on_readyRead_slot();
void send(QString mes);
private:
Ui::chatser1 *ui;
//定义一个服务器指针
QTcpServer *server;
//定义客户端指针,盛放连接的客户端
QList<QTcpSocket *> socketList;
};
#endif // CHATSER1_H
chatser1.cpp
#include "chatser1.h"
#include "ui_chatser1.h"
chatser1::chatser1(QWidget *parent)
: QWidget(parent)
, ui(new Ui::chatser1)
{
ui->setupUi(this);
server = new QTcpServer(this);
}
chatser1::~chatser1()
{
delete ui;
}
void chatser1::on_startBtn_clicked()
{
quint16 port = quint16(ui->lineEdit->text().toInt());
server->listen(QHostAddress::Any,port);
//将相应的控件设置为 不可用状态
ui->lineEdit->setEnabled(false);
ui->startBtn->setEnabled(false);
//当有新的客户端连接到服务器后,会出发一个newconnectioon的信号
connect(server,&QTcpServer::newConnection,this,&chatser1::on_newConnection_slot);
}
void chatser1::on_newConnection_slot()
{
QTcpSocket * socket= server->nextPendingConnection();
//将套接字放入套接字链表中
socketList.append(socket);
//当服务器接收到客户端传过来的消息,会触发一个readyRead信号
connect(socket,&QTcpSocket::readyRead,this,&chatser1::on_readyRead_slot);
}
void chatser1::on_readyRead_slot()
{
for(int i=0;i<socketList.count();i++)
{
if(socketList.at(i)->state() == false)
{
socketList.removeAt(i);
}
}
for (quint16 i =0;i<socketList.count();i++)
{
if(socketList.at(i)->bytesAvailable())
{
QString mes = QString::fromLocal8Bit( socketList.at(i)->readAll());
ui->listWidget->addItem(mes);
send(mes);
}
}
}
//发送
void chatser1::send(QString mes)
{
for(int i=0;i<socketList.count();i++)
{
socketList.at(i)->write(mes.toLocal8Bit());
}
}
客户端:
chatcli.h
#ifndef CHATCLI_H
#define CHATCLI_H
#include <QWidget>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class chatcli; }
QT_END_NAMESPACE
class chatcli : public QWidget
{
Q_OBJECT
public:
chatcli(QWidget *parent = nullptr);
~chatcli();
private slots:
void on_connectBtn_clicked();
void on_connected_slot();
void on_disconnected_slot();
void on_readyRead_slot();
void on_sendBtn_clicked();
private:
Ui::chatcli *ui;
//定义客服端套接字
QTcpSocket *socket;
QString userName;
//连接状态
bool isOK;
};
#endif // CHATCLI_H
chatcli.cpp
#include "chatcli.h"
#include "ui_chatcli.h"
#include <QHostAddress>
chatcli::chatcli(QWidget *parent)
: QWidget(parent)
, ui(new Ui::chatcli)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
isOK = false;
//将connected信号连接到自定义槽函数
connect(socket,&QTcpSocket::connected,this,&chatcli::on_connected_slot);
connect(socket,&QTcpSocket::disconnected,this,&chatcli::on_disconnected_slot);
connect(socket,&QTcpSocket::readyRead,this,&chatcli::on_readyRead_slot);
}
chatcli::~chatcli()
{
delete ui;
}
void chatcli::on_connectBtn_clicked()
{
QString ip=ui->ipEdit->text();
quint16 port = quint16( ui->portEdit->text().toInt());
if(isOK == false )
{
//连接服务器
socket->connectToHost(QHostAddress(ip),port);
//一旦连接成功,触发connect信号
ui->portEdit->setEnabled(false);
ui->ipEdit->setEnabled(false);
ui->usernameEdit->setEnabled(false);
//将按钮文本改为断开连接
ui->connectBtn->setText("断开连接");
isOK = true;
}
else
{
userName = ui->usernameEdit->text();
QString mes = userName + "离开群聊";
socket->write(mes.toLocal8Bit());
//断开服务器
socket->disconnectFromHost();
//一旦连接成功,触发disconnect信号
ui->portEdit->setEnabled(true);
ui->ipEdit->setEnabled(true);
ui->usernameEdit->setEnabled(true);
//将按钮文本改为连接
ui->connectBtn->setText("连接服务器");
isOK = false;
}
}
void chatcli::on_connected_slot()
{
userName = ui->usernameEdit->text();
QString mes = userName + "加入群聊";
socket->write(mes.toLocal8Bit());
}
void chatcli::on_disconnected_slot()
{
}
void chatcli::on_readyRead_slot()
{
//获取套接字的数据
QString mes = QString::fromLocal8Bit(socket->readAll() );
//将数据显示在list widget中
ui->listWidget->addItem(mes);
}
void chatcli::on_sendBtn_clicked()
{
userName = ui->usernameEdit->text();
QString mes = userName + ":" +ui->mesEdit->text();
socket->write(mes.toLocal8Bit());
ui->mesEdit->clear();
}