服务器:
头文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include<QDebug>
#include<QList>
#include<QListWidget>
#include<QLabel>
#include<QLineEdit>
#include<QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
//客户端指针
QTcpSocket *client;
//存储用户名
QString uname;
//聊天框
QListWidget *text;
//消息发送框
QLineEdit *msg;
//发送按钮
QPushButton *send;
//用户名、
QLabel *userLab;
//IP
QLabel *ipLab;
//PORT
QLabel *portLab;
//用户输入框
QLineEdit *unameEdit;
//IP输入框
QLineEdit *ipEdit;
//端口输入框
QLineEdit *portEdit;
//连接服务器按钮
QPushButton *bconnect;
//断开服务器按钮
QPushButton *bdisconnect;
public slots:
//连接按钮槽函数
void connectBtn_clicked();
//声明自定义处理connected信号的槽函数
void connected_slot();
//声明自定义处理readyRead信号的槽函数
void readyRead_slot();
//声明自定义处理disconnected信号的槽函数
void disconnected_slot();
//发送按钮槽函数
void sendBtn_clicked();
//断开连接槽函数
void disconnectBtn_clicked();
};
#endif // WIDGET_H
widget.cpp文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setFixedSize(720,680);
//聊天框
text = new QListWidget(this);
text->setFixedSize(720,400);
//消息发送框
msg = new QLineEdit(this);
msg->resize(500,50);
msg->move(10,420);
//发送按钮
send = new QPushButton(this);
send->setText("发送");
send->resize(150,50);
send->move(520,420);
//用户名
userLab = new QLabel(this);
userLab->setText("用户名:");
userLab->setAlignment(Qt::AlignCenter);
userLab->resize(100,30);
userLab->move(30,500);
//IP
ipLab = new QLabel(this);
ipLab->setText("IP:");
ipLab->setAlignment(Qt::AlignCenter);
ipLab->resize(100,30);
ipLab->move(30,550);
//PORT
portLab = new QLabel(this);
portLab->setText("Port:");
portLab->setAlignment(Qt::AlignCenter);
portLab->resize(100,30);
portLab->move(30,600);
//用户输入框
unameEdit = new QLineEdit(this);
unameEdit->resize(300,30);
unameEdit->move(140,500);
//IP输入框
ipEdit = new QLineEdit(this);
ipEdit->resize(300,30);
ipEdit->move(140,550);
//端口输入框
portEdit = new QLineEdit(this);
portEdit->resize(300,30);
portEdit->move(140,600);
//连接服务器按钮
bconnect = new QPushButton(this);
bconnect->resize(120,50);
bconnect->setText("连接");
bconnect->move(520,500);
//断开服务器按钮
bdisconnect = new QPushButton(this);
bdisconnect->resize(120,50);
bdisconnect->setText("断开连接");
bdisconnect->move(520,580);
client = new QTcpSocket(this);
//连接按钮信号
connect(bconnect,&QPushButton::clicked,this,&Widget::connectBtn_clicked);
//连接上后客户端自动发送一个connected信号,只需要连接一次
connect(client,&QTcpSocket::connected,this,&Widget::connected_slot);
//如果服务器有数据发送给该客户端,那么该套接字就会自动发射一个readyRead信号
connect(client, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
//发送按钮
connect(send,&QPushButton::clicked,this,&Widget::sendBtn_clicked);
//当成功与服务器断开连接后,该客户端就会自动发射一个disconnected的信号
connect(client, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
}
Widget::~Widget()
{
delete ui;
}
//连接按钮槽函数
void Widget::connectBtn_clicked()
{
//获取ip和端口
QString ip = ipEdit->text();
quint16 port = portEdit->text().toUInt();
//连接主机
client->connectToHost(ip,port);
}
//声明自定义处理connected信号的槽函数
void Widget::connected_slot()
{
QMessageBox::information(this,"","连接服务器成功");
uname = unameEdit->text();
QString msgs = uname+":进入聊天室";
client->write(msgs.toLocal8Bit());
msg->setEnabled(true);
send->setEnabled(true);
bdisconnect->setEnabled(true);
unameEdit->setEnabled(false);
ipEdit->setEnabled(false);
portEdit->setEnabled(false);
bconnect->setEnabled(false);
}
//声明自定义处理readyRead信号的槽函数
void Widget::readyRead_slot()
{
//接收到服务器消息后
QByteArray msgbox = client->readAll();
//显示
text->addItem(QString::fromLocal8Bit(msgbox));
}
//声明自定义处理disconnected信号的槽函数
void Widget::disconnected_slot()
{
QString msgbox = uname+":离开聊天室";
client->write(msgbox.toLocal8Bit());
//断开后客户端会发送一个disconnected信号
client->disconnectFromHost();
}
//发送按钮槽函数
void Widget::sendBtn_clicked()
{
QString msgbox = msg->text();
msgbox = uname+":"+msgbox;
//发送
client->write(msgbox.toLocal8Bit());
msg->clear();
}
//断开连接槽函数
void Widget::disconnectBtn_clicked()
{
QMessageBox::information(this,"","成功断开");
msg->setEnabled(false);
send->setEnabled(false);
bdisconnect->setEnabled(false);
unameEdit->setEnabled(true);
ipEdit->setEnabled(true);
portEdit->setEnabled(true);
bconnect->setEnabled(true);
}
客户端
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include<QDebug>
#include<QList>
#include<QListWidget>
#include<QLabel>
#include<QLineEdit>
#include<QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
//定义服务器指针
QTcpServer *server;
//定义客户端容器
QList<QTcpSocket*> socketList;
//对话框
QListWidget *text;
//端口号
QLabel * l_port;
//端口输入框
QLineEdit *edit_port;
//启动按钮
QPushButton *bstart;
private slots:
//按键槽函数
void start_clicked();
//连接槽函数
void newConnection_slot();
//readyRead信号处理槽函数
void readyRead_slot();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setFixedSize(680,500);
//对话框
text = new QListWidget(this);
text->setFixedSize(680,350);
//端口号
l_port = new QLabel(this);
l_port->setText("端口号:");
l_port->resize(50,30);
l_port->move(50,400);
//端口输入框
edit_port = new QLineEdit(this);
edit_port->resize(380,30);
edit_port->move(120,400);
//启动按钮
bstart = new QPushButton(this);
bstart->setText("启动服务器");
bstart->resize(100,30);
bstart->move(520,400);
server = new QTcpServer(this);
connect(bstart,&QPushButton::clicked,this,&Widget::start_clicked);
}
Widget::~Widget()
{
delete ui;
}
void Widget::start_clicked()
{
qDebug()<<"ok"; //测试
//判断输入框中是否有内容
if(edit_port->text() == NULL)
{
QMessageBox::information(this,"错误","端口号为空!");
}
else
{
//获取输入框中的内容
quint16 port = edit_port->text().toUInt();
qDebug()<<port;
QString ip = "192.168.1.2";
QHostAddress address(ip);
//将服务器设置成监听状态,监听客户段发来的连接请求
if(server->listen(QHostAddress::Any,port))
{
QMessageBox::information(this,"","服务器启动成功");
}
else
{
QMessageBox::information(this,"","服务器启动失败");
}
//此时服务器已经进入监听状态,客户段发来连接请求,服务器就会自动发射一个newConnext信号
connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
}
}
void Widget::newConnection_slot()
{
qDebug()<<"有客户连接";
//获取最新连接的客户段套接字
QTcpSocket *client = server->nextPendingConnection();
//将套接字放入客户端容器
socketList.push_back(client);
//监听套接字,有数据则客户端会发送一个readyRead信号
connect(client,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
void Widget::readyRead_slot()
{
//移除无效客户端
for (int i = 0;i<socketList.count();i++)
{
//套接字状态为0表示无效客户端
if(socketList.at(i)->state() == 0)
{
socketList.removeAt(i);
}
}
//遍历套接字有消息发送给其他客户端
for (int i = 0;i<socketList.count();i++)
{
//获取套接字是否有有效数据
if(socketList.at(i)->bytesAvailable() != 0)
{
//获取套接字内信息
QByteArray msg = socketList.at(i)->readAll();
text->addItem(QString::fromLocal8Bit(msg));
for (int j = 0;j<socketList.count();j++)
{
socketList.at(j)->write(msg);
}
}
}
}