以下是修改后的多线程并能管理用户列表的client端和server端代码,以及生成的相应Qt5的clientui.ui和serverui.ui代码:
===========clientui.cpp=========== #include “clientui.h” #include “ui_clientui.h”
ClientUI::ClientUI(QWidget *parent) :
QWidget(parent), ui(new Ui::ClientUI) {
ui->setupUi(this);
client = new QTcpSocket(this);
ui->Button_send->setEnabled(false);
/* 连接服务器 */
connect(ui->Button_connection,&QPushButton::released,this, [=]() {
client->connectToHost(ui->lineEdit_ip->text(),ui->lineEdit_d->text().toInt());
});
/* 连接成功 */
connect(client,&QTcpSocket::connected,this, [&]() {
ui->Button_send->setEnabled(true);
ui->label_prompt->setText("已连接");
ui->textEdit_receive->append("连接成功……");
});
/* 发送到服务器 */
connect(ui->Button_send,&QPushButton::released,this, [&]() {
QString data = ui->textEdit_edit->toPlainText();
if(data.length() > 0) {//如果输入框不为空才可以发送
client->write(data.toUtf8());
QString data1 = "已发送:"+data;
ui->textEdit_receive->append(data1);
ui->textEdit_edit->setText("");
} else {
ui->textEdit_receive->append("输入信息");
}
});
/* 接收信息 */
connect(client,&QTcpSocket::readyRead,this, [&]() {
QString msg = "收到:" + client->readAll();
ui->textEdit_receive_2 ->append(msg);
});
// 关闭客户端
connect(ui->Button_disconnect, &QPushButton::released, this, [&]() {
client->disconnectFromHost();
ui->Button_send->setEnabled(false);
});
/* 断开连接 */
connect(client,&QTcpSocket::disconnected,this, [&]() {
ui->label_prompt->setText("待连接……");
ui->textEdit_receive->append("断开连接……");
});
}
ClientUI::~ClientUI() {
delete ui;
} ==============clientui.h============== #ifndef CLIENTUI_H #define CLIENTUI_H
#include
QT_BEGIN_NAMESPACE namespace Ui { class ClientUI; } QT_END_NAMESPACE
class ClientUI : public QWidget {
Q_OBJECT
public:
explicit ClientUI(QWidget *parent = nullptr);
~ClientUI() override;
private:
Ui::ClientUI *ui;
QTcpSocket *client;
};
#endif // CLIENTUI_H
=============serverui.cpp============ #include “serverui.h” #include “ui_serverui.h”
ServerThread::ServerThread(qintptr socketDescriptor, QObject* parent) : QThread(parent), socketDescriptor(socketDescriptor) { }
void ServerThread::run() { QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}
QString ip= QHostAddress(tcpSocket.peerAddress().toIPv4Address()).toString(); qint16 port =tcpSocket.peerPort(); QString ipDate=QString(“%1:%2”).arg(ip).arg(port); // qDebug() << “客户信息:” << ipDate;
// 发送欢迎消息 QString message = “已成功连接服务器,您的IP地址为:” + ipDate; tcpSocket.write(message.toUtf8());
// 将新客户端添加到列表中 emit addClient(ipDate);
// 监听客户端发送的消息 while (tcpSocket.state() == QTcpSocket::ConnectedState) {
if (tcpSocket.waitForReadyRead(1000)) {
QByteArray buffer = tcpSocket.readAll();
QString msg(buffer);
emit newMessage(ipDate, msg);
}
}
// 关闭socket连接 tcpSocket.disconnectFromHost(); tcpSocket.waitForDisconnected(); }
ServerUI::ServerUI(QWidget *parent ) :
QWidget(parent),
ui(new Ui::ServerUI)
{
ui->setupUi(this);
// 获取本机IP地址并显示在窗口标题栏中
QString localeIp = getLocalIp();
setWindowTitle(windowTitle() + "---IP地址:" + localeIp);
server = new QTcpServer(this);
connect(ui->Btbind,&QPushButton::released,this,&ServerUI::startServer);
//
/* 发送信息 */
connect(ui->Button_send,&QPushButton::released,this,&ServerUI::senddata);
}
void ServerUI::startServer() {
int port = ui->lineEdit_d->text().toInt();
if(port > 0) { //如果输入栏不为空才可以发送
/* 绑定绑定信息 */
server->listen(QHostAddress::Any,port);
ui->label_prompt->setText("已启动");
ui->textEdit_log->append("服务器启动成功");
ui->Btbind->setEnabled(false);
ui->lineEdit_d->setReadOnly(true);
// 监听客户端连接请求,并将新连接交给新线程处理
connect(server, &QTcpServer::newConnection, this, [=]() {
QThread* thread = new QThread;
ServerThread* serverThread = new ServerThread(server->nextPendingConnection()->socketDescriptor());
serverThread->moveToThread(thread);
thread->start();
connect(thread, &QThread::finished, serverThread, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
// 监听ServerThread中的信号
connect(serverThread, &ServerThread::newMessage,
this, [=](QString ipDate, QString msg) {
ui->textEdit_log_2 ->append(ipDate + ": " + msg);
});
// 监听ServerThread中的信号
connect(serverThread,&ServerThread::addClient,this,[=](QString ipDate){
ui->users->appendPlainText(ipDate);
});
});
}
else {
ui->textEdit_log->append("输入端口信息");
}
}
void ServerUI::senddata() {
if (ui->users->toPlainText().isEmpty())
return;
QString data = ui->textEdit_edit ->toPlainText();
if(data.length() > 0) { //如果输入栏不为空才可以发送
foreach (const QString& clientIpPort, ui->users -> toPlainText().split("\n")) {
QStringList list = clientIpPort.split(":");
QTcpSocket* socket = new QTcpSocket;
socket ->connectToHost(list[0], list[1].toInt());
if (socket ->waitForConnected(100)) {
socket ->write(data.toUtf8());
QString data1 = "已发送:" + data;
ui -> textEdit_log_2 -> append("给" + clientIpPort + " " + data1);
socket ->disconnectFromHost();
}
}
ui->textEdit_edit ->setText("");
}
else {
ui->textEdit_log_2 ->append("输入信息");
}
}
QString ServerUI::getLocalIp(){
QString hostName = QHostInfo::localHostName();
QHostInfo hostInfo = QHostInfo::fromName(hostName);
// qDebug() << “Local Host Name:” << hostName;
QString locaIp = "null Qstring";
QList<QHostAddress> list = hostInfo.addresses();
if (list.empty())
return locaIp;
foreach (QHostAddress addr, list) {
if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
locaIp = addr.toString();
break;
}
}
return locaIp;
}
ServerUI::~ServerUI() { delete ui; } ==============serverui.h============== #ifndef SERVERUI_H #define SERVERUI_H
#include
QT_BEGIN_NAMESPACE namespace Ui { class ServerUI; } QT_END_NAMESPACE
class ServerThread : public QThread { Q_OBJECT
public: explicit ServerThread(qintptr socketDescriptor, QObject* parent = nullptr);
protected: void run() override;
signals: void error(QTcpSocket::SocketError socketError); void newMessage(QString ipDate, QString msg); void addClient(QString ipDate);
private: qintptr socketDescriptor; };
class ServerUI : public QWidget {
Q_OBJECT
public:
explicit ServerUI(QWidget *parent = nullptr);
~ServerUI() override;
private slots:
// 这个是按钮点击事件的一种写法,通常以 on_控件名字_clicked来表示,这里就是我们之前设置的一个按钮的点击事件
void senddata();
void startServer();
private:
Ui::ServerUI *ui;
QTcpServer *server;
QString getLocalIp(); //获取本机 IP
};
#endif // SERVERUI_H
===========clientui.ui=============
<?xml version=“1.0” encoding=“UTF-8”?>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item spacing="6" layoutDirection="LeftToRight" >
<widget class="QLabel" name="">
<property name="text">
<string>IP地址:</string>
</property>
</widget>
</item>
<item spacing="6" layoutDirection="LeftToRight" >
<widget class="QLineEdit" name = "lineEdit_ip"/>
</item>
<!-- 端口号 -->
<!----><item spacing = "6">
<!----><widget class = "QLabel" name = "label_2"/>
<!----><property name = "text">
<!----><string>端口号:</string></property></widget></item>
<!----><item alignment = "Qt::AlignLeft|Qt::AlignVCenter"><widget class = "QLineEdit"
name = "lineEdit_d"><property name = "maxLength