QT聊天室

使用Qt库中的 <QTcpServer>  和<QTcpSocket>类实现局域网络下的聊天室。

分为服务端和客户端;

服务端接收来自各个客户端的信息,并发送到所有客户端;

客户端用于用户登陆及聊天。

客户端:

使用<QTcpSocket>类即可;

首先在 工程文件.pro中加入一行:

QT       += network

创建工程,然后用一个dialog实现主窗体就行了;

用Qt设计器添加控件:

以下是Dialog.h源码:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTcpSocket>
#include <QHostAddress>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
  Q_OBJECT

public:
  explicit Dialog(QWidget *parent = 0);
  ~Dialog();

private:
  Ui::Dialog *ui;

  bool connectStatus;
  //
  int port;
  QHostAddress *serverIP;
  QString userName;
  QTcpSocket *tcpSocket;

public slots:
  void slotEnter();
  void slotConnected();
  void slotDisconnected();
  void slotDataReceived();
  void slotSend();
};

#endif // DIALOG_H

以下是Dialog.cpp源码:

#include "dialog.h"
#include "ui_dialog.h"

#include <QMessageBox>
#include <QHostAddress>

Dialog::Dialog(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::Dialog)
{
  ui->setupUi(this);
  this->setFixedSize(400,500);
  this->setWindowTitle("TCP Client");

  ui->portLineEdit->setText("45454");
  ui->userNameLineEdit->setText("UserName");

  connect(ui->enterButton,SIGNAL(clicked()),this,SLOT(slotEnter()));
  connect(ui->sendButton,SIGNAL(clicked()),this,SLOT(slotSend()));

  this->serverIP = new QHostAddress();
  this->connectStatus = false;
  ui->sendButton->setEnabled(false);
}

Dialog::~Dialog()
{
  delete ui;
}

void Dialog::slotEnter()
{
  if(!this->connectStatus)
  {
    //---------------------------------------------------
    if(ui->userNameLineEdit->text()=="")
    {
      QMessageBox::information(this,tr("error"),tr("User name Error ! "));
    }
    this->userName = ui->userNameLineEdit->text();

    if(ui->serverIPLineEdit->text()=="")
    {
      QMessageBox::information(this,tr("error"),tr("Server Address Error ! "));
    }
    this->serverIP->setAddress(ui->serverIPLineEdit->text());

    if(ui->portLineEdit->text() == "")
    {
      QMessageBox::information(this,tr("error"),tr("Port Error ! "));
    }
    this->port = ui->portLineEdit->text().toInt();
    //---------------------------------------------------

    this->tcpSocket = new QTcpSocket(this);
    connect(this->tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
    connect(this->tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));

    this->tcpSocket->connectToHost(*this->serverIP,this->port); //
  }
  else
  {
    QString msg = this->userName + tr(":leave chat Room");
    this->tcpSocket->write(msg.toLatin1(),msg.length());

    this->tcpSocket->disconnectFromHost();
  }
}

void Dialog::slotConnected()
{
  ui->sendButton->setEnabled(true);
  ui->enterButton->setText(tr("Leave"));
  connect(this->tcpSocket,SIGNAL(readyRead()),this,SLOT(slotDataReceived()));

  QString msg = this->userName + tr(":Enter Chat room");
  this->tcpSocket->write(msg.toLatin1(),msg.length());
  this->connectStatus = true;
  QMessageBox::information(this,tr("Connected"),tr("Entered the Chat room"));
}

void Dialog::slotDisconnected()
{
  ui->sendButton->setEnabled(false);
  ui->enterButton->setText(tr("Enter"));
  this->connectStatus = false;

  QMessageBox::information(this,tr("Disconnected"),tr("Exited the Chat room"));
}

void Dialog::slotSend()
{
  if(ui->sendLineEdit->text()=="")
  {
    return;
  }
  QString msg = this->userName+" : "+ui->sendLineEdit->text();
  this->tcpSocket->write(msg.toLatin1(),msg.length());
  ui->sendLineEdit->clear();
}

void Dialog::slotDataReceived()
{
  while(tcpSocket->bytesAvailable()>0)
  {
    QString msg = this->tcpSocket->readAll();
    ui->contentListWidget->addItem(msg.left(msg.length()));
  }
}

然后是服务端:

同样,首先在 工程文件.pro中加入一行:

QT       += network

用Widgets实现主窗体:

服务端实现了两个类:<clientTCPsocket>类和<TCPserver>类,分别继承自<QTcpSocket><QTcpServer>;


clientTCPsocket.h:
#ifndef CLIENTTCPSOCKET_H
#define CLIENTTCPSOCKET_H

#include <QTcpSocket>
#include <QObject>

class clientTCPsocket : public QTcpSocket
{
  Q_OBJECT
public:
  clientTCPsocket(QObject *parent = 0);

signals:
  void updateClients(QString,int);
  void disconnected(int);

public slots:
  void dataReceived();
  void slotDisconnected();

};

#endif // CLIENTTCPSOCKET_H

clientTCPsocket.cpp:

#include "clienttcpsocket.h"

clientTCPsocket::clientTCPsocket(QObject *parent) :
  QTcpSocket(parent)
{
  connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
  connect(this,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected()));
}

void clientTCPsocket::dataReceived()
{
  while(this->bytesAvailable()>0)
  {
    QString msg = this->readAll();
    int length = msg.length();
    emit updateClients(msg,length);
  }
}

void clientTCPsocket::slotDisconnected()
{
  emit disconnected(this->socketDescriptor()); //
}

TCPserver.h:

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QTcpServer>
#include <QTcpSocket>
#include <QObject>
#include <clienttcpsocket.h>

class TCPserver : public QTcpServer
{
  Q_OBJECT
public:
  TCPserver(QObject *parent = 0,int port = 0);
  QList<clientTCPsocket*>clientTCPsocketList;

signals:
  void updateServer(QString,int);

public slots:
  void updateClients(QString msg, int length);
  void slotDisconnected(int descriptor);
  void acceptConnection();

};

#endif // TCPSERVER_H

TCPserver.cpp:

#include "tcpserver.h"


TCPserver::TCPserver(QObject *parent,int port) :
  QTcpServer(parent)
{
  this->listen(QHostAddress::Any,port);
  connect(this,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
}

void TCPserver::acceptConnection()
{
  clientTCPsocket *TCPsocket = new clientTCPsocket(this);
  connect(TCPsocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));
  connect(TCPsocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));
  TCPsocket->setSocketDescriptor(this->nextPendingConnection()->socketDescriptor());
  this->clientTCPsocketList.append(TCPsocket);
}

void TCPserver::updateClients(QString msg, int length)
{
  emit updateServer(msg,length);							  //
  for(int i=0;i<clientTCPsocketList.count();i++)
  {
    QTcpSocket *item = clientTCPsocketList.at(i);
    item->write(msg.toLatin1(),length);
  }
}

void TCPserver::slotDisconnected(int descriptor)
{
  for(int i =0;i<clientTCPsocketList.count();i++)
  {
    QTcpSocket *item = clientTCPsocketList.at(i);
    if(item->socketDescriptor()==descriptor)
    {
      clientTCPsocketList.removeAt(i);
      return;
    }
  }
  return;
}

Widgets中创建并初始化一个TCPserver对象;

widgets.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <tcpserver.h>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
  Q_OBJECT

public:
  explicit Widget(QWidget *parent = 0);
  ~Widget();

private:
  Ui::Widget *ui;

  int port;
  TCPserver *server;

public slots:
    void slotCreateServer();
    void updateServer(QString msg, int length);
};

#endif // WIDGET_H

widgets.cpp:

#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>

Widget::Widget(QWidget *parent) :
  QWidget(parent),
  ui(new Ui::Widget)
{
  ui->setupUi(this);
  setWindowTitle(tr("TCP server"));
  this->setFixedSize(400,500);

  ui->PortlLineEdit->setText("45454");
  connect(ui->CreateBtn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));

}

Widget::~Widget()
{
  delete ui;
}

void Widget::slotCreateServer()
{
  //*******************************************
  if(ui->PortlLineEdit->text() == "")
  {
    QMessageBox::information(this,tr("error"),tr("Port Error ! "));
  }
  this->port = ui->PortlLineEdit->text().toInt();
  //*******************************************

  this->server = new TCPserver(this,this->port);
  connect(this->server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));
  ui->CreateBtn->setEnabled(false);
}

void Widget::updateServer(QString msg, int length)
{
  ui->ContentListWidget->addItem(msg.left(length));
}

这样服务端和客户端都实现完成;

运行效果:

服务端:

客户端:

<think>好的,我现在需要帮助用户解决如何使用Qt开发聊天室的问题。首先,用户提到了他们之前看到的引用内容,其中涉及QTcpSocket和QThread,还有示例代码中的设置对话框。不过这些引用可能不完全符合用户当前的需求,但可以作为参考。 我应该先回忆一下Qt网络编程模块。Qt提供了QTcpServer和QTcpSocket类,用于实现TCP服务器和客户端。聊天室通常需要服务器处理多个客户端的连接,并转发消息,所以需要用到多线程或者异步处理。 接下来,用户可能需要一个基本的步骤指南。首先创建服务器端,监听端口,接受客户端连接。然后客户端连接到服务器,发送和接收消息。同时,界面部分需要使用Qt的Widgets或者QML来设计。 考虑到用户可能需要示例代码的结构,我应该分服务器和客户端两部分来讲解。服务器端使用QTcpServer,每当有新连接时创建一个QTcpSocket来处理。客户端使用QTcpSocket连接到服务器,发送消息,并接收服务器广播的消息。 还要注意线程处理,防止界面卡顿。可能需要在客户端和服务器端使用QThread,或者在socket通信中使用异步方式。例如,在客户端,数据的接收可以使用readyRead信号连接到槽函数,这样就不会阻塞主线程。 另外,引用中提到的Dlg_setting类中的网络地址获取,可能是在设置服务器IP和端口时需要的。用户可能需要知道如何获取本机IP地址,这在Qt中可以通过QNetworkInterface类实现。 最后,用户可能需要知道如何处理多个客户端的消息转发,服务器需要维护一个客户端列表,并在收到消息时遍历列表发送给所有客户端。同时,要处理客户端的断开连接,从列表中移除。 可能的问题点包括:网络通信的异步处理、数据的正确读写、编码问题、线程安全等。需要提醒用户注意这些方面,并提供简单的示例代码说明基本流程。</think>### Qt聊天室开发指南 使用Qt开发聊天室需掌握QTcpServer和QTcpSocket类的使用,以下是核心实现步骤: #### 一、服务器端实现 1. **创建TCP服务器** ```cpp // 创建服务器对象 QTcpServer *server = new QTcpServer(this); connect(server, &QTcpServer::newConnection, this, &Server::newClient); server->listen(QHostAddress::Any, 8888); ``` 2. **维护客户端列表** ```cpp QList<QTcpSocket*> clients; // 存储所有连接的客户端 ``` 3. **消息广播机制** ```cpp void Server::broadcastMessage(const QString &msg) { foreach(QTcpSocket *client, clients) { client->write(msg.toUtf8()); } } ``` #### 二、客户端实现 1. **建立连接** ```cpp QTcpSocket *socket = new QTcpSocket(this); socket->connectToHost("127.0.0.1", 8888); ``` 2. **消息接收处理** ```cpp connect(socket, &QTcpSocket::readyRead, [=](){ QByteArray data = socket->readAll(); QString msg = QString::fromUtf8(data); // 更新UI显示消息 }); ``` #### 三、关键功能实现 1. **获取本机IP地址**(参考引用[2]) ```cpp QStringList getLocalIPs() { QStringList ips; foreach(const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { foreach(const QHostAddress &address, interface.addressEntries()) { if(address.protocol() == QAbstractSocket::IPv4Protocol) ips << address.ip().toString(); } } return ips; } ``` 2. **多线程处理**(参考引用[1]) ```cpp class ClientThread : public QThread { Q_OBJECT void run() override { // 在此处理网络通信 } }; ``` #### 四、完整示例结构 ``` ChatServer/ ├── server.pro ├── serverwindow.cpp // 服务器界面 └── servercore.cpp // 服务器逻辑 ChatClient/ ├── client.pro ├── clientwindow.cpp // 客户端界面 └── clientnetwork.cpp // 网络模块 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值