本文实例为大家分享了QT实现TCP网络聊天室的具体代码,供大家参考,具体内容如下服务器:serverdialog.h#ifndefSERVERDIALOG_H#defineSERVERDIALOG...

本文实例为大家分享了QT实现TCP网络聊天室的具体代码,供大家参考,具体内容如下

服务器:

serverdialog.h

#ifndef SERVERDIALOG_H
#define SERVERDIALOG_H

#include <QDialog>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QTimer>

namespace Ui {
class ServerDialog;
}

class ServerDialog : public QDialog
{
  Q_OBJECT

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

private slots:
  //创建服务器按钮对应的槽函数
  void on_pushButton_clicked();
  //响应客户端连接请求的槽函数
  void onNewConnection();
  //接收客户端聊天消息的槽函数
  void onReadyRead();
  //转发聊天消息给其它客户端的槽函数
  void sendMessage(const QByteArray&);
  //定时器检查客户端套接字是否为正常连接状态的槽函数
  void onTimeout(void);
private:
  Ui::ServerDialog *ui;
  QTcpServer tcpServer;//TCP服务器
  quint16 port;//服务器端口,quint16-->unsigned short
  QList<QTcpSocket*> tcpClientList;//容器:保存和客户端通信的套接字
  QTimer timer;//定时器,定时检查容器中和客户端通信的套接字是否为正常连接状态
};


#endif // SERVERDIALOG_H

serverdialog.cpp

#include "serverdialog.h"
#include "ui_serverdialog.h"

ServerDialog::ServerDialog(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::ServerDialog)
{
  ui->setupUi(this);
}

ServerDialog::~ServerDialog()
{
  delete ui;
}
//创建服务器按钮对应的槽函数
void ServerDialog::on_pushButton_clicked()
{
  //获取服务器端口
  port = ui->lineEdit->text().toShort();
  //设置监听服务器的IP和端口
  //QHostAddress::Any ==> QHostAddress("0.0.0.0");
  if(tcpServer.listen(QHostAddress::Any,port)==false){
    qDebug() << "创建服务器失败";
    return;
  }
  else{
    qDebug() << "创建服务器成功";
    //当有客户端向服务器发送连接请求时,发送信号newConnection
    connect(&tcpServer,SIGNAL(newConnection()),
        this,SLOT(onNewConnection()));
    //禁用端口输入和创建服务器按钮
    ui->lineEdit->setEnabled(false);
    ui->pushButton->setEnabled(false);

    //定时器到时发送信号:timeout
    connect(&timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
    //开启定时器,每隔3秒检查一次
    timer.start(3000);

  }
}
//响应客户端连接请求的槽函数
void ServerDialog::onNewConnection()
{
  //获取和客户端通信的套接字
  QTcpSocket* tcpClient = tcpServer.nextPendingConnection();
  //保存套接字到容器中
  tcpClientList.append(tcpClient);
  //当客户端给服务器发送消息时,tcpClient发送信号readyRead
  connect(tcpClient,SIGNAL(readyRead()),
      this,SLOT(onReadyRead()));
}
//接收客户端聊天消息的槽函数
void ServerDialog::onReadyRead()
{
  //遍历检查哪个客户端有消息
  for(int i=0;i<tcpClientList.size();i++){
    //at(i):获取容器中第i套接字(QTcpSocket*)
    //bytesAvailable:获取当前套接字等待读取消息的字节数,如果为0表示没有消息,如果
    //大于0说明有消息.
    if(tcpClientList.at(i)->bytesAvailable()){
      //读取消息并保存
      QByteArray buf = tcpClientList.at(i)->readAll();
      //显示消息
      ui->listWidget->addItem(buf);
      //回滚到最底部(最新消息)
      ui->listWidget->scrollToBottom();
      //转发消息给其它客户端
      sendMessage(buf);
    }
  }
}
//转发聊天消息给其它客户端的槽函数
void ServerDialog::sendMessage(const QByteArray& msg)
{
  for(int i=0;i<tcpClientList.size();i++){
    tcpClientList.at(i)->write(msg);
  }
}
//定时器检查客户端套接字是否为正常连接状态的槽函数
void ServerDialog::onTimeout(void)
{
  for(int i=0;i<tcpClientList.size();i++){
    //state():获取第i个套接字的连接状态
    //UnconnectedState:表示未连接(断开连接)
    if(tcpClientList.at(i)->state() ==
        QAbstractSocket::UnconnectedState){
      //从容器中将断开连接的套接字移除
      tcpClientList.removeAt(i);
      --i;
    }
  }
}php

main.cpp

#include "serverdialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  ServerDialog w;
  w.show();

  return a.exec();
}

客户端:

clientdialog:

#ifndef CLIENTDIALOG_H
#define CLIENTDIALOG_H

#include <QDialog>
//QT += network
#include <QTcpSocket>
#include <QHostAddress>
#include <QMessageBox>

namespace Ui {
class ClientDialog;
}

class ClientDialog : public QDialog
{
  Q_OBJECT

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

private slots:
  //发送按钮对应的槽函数
  void on_sendButton_clicked();
  //连接服务器按钮对应的槽函数
  void on_connectButton_clicked();
  //和服务器连接成功时执行的槽函数
  void onConnected(void);
  //和服务器断开连接时执行的槽函数
  void onDisconnected(void);
  //接收服务器转发聊天消息的槽函数
  void onReadyRead(void);
  //网络通信异常时执行的槽函数
  void onError(void);
private:
  Ui::ClientDialog *ui;
  bool status;//客户端状态标记,true:在线,false:离线状态
  QTcpSocket tcpSocket;//和服务器通信的tcp套接字
  QHostAddress serverIp;//服务器地址
  quint16 serverPort;//服务器端口
  QString username;//聊天室昵称
};

#endif // CLIENTDIALOG_H

clientdialog.cpp

#include "clientdialog.h"
#include "ui_clientdialog.h"

ClientDialog::ClientDialog(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::ClientDialog)
{
  ui->setupUi(this);
  status = false;
  //和服务器连接成功时,tcpSocket发送信号:connected
  connect(&tcpSocket,SIGNAL(connected()),
      this,SLOT(onConnected()));
  //和服务器断开连接时,tcpSocket发送信号:disconnected
  connect(&tcpSocket,SIGNAL(disconnected()),
      this,SLOT(onDisconnected()));
  //收到聊天消息时,tcpSocket发送信号:readyRead
  connect(&tcpSocket,SIGNAL(readyRead()),
      this,SLOT(onReadyRead()));
  //网络通信异常时,tcpSocket发送信号:error
  connect(&tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
      this,SLOT(onError()));
}

ClientDialog::~ClientDialog()
{
  delete ui;
}
//发送按钮对应的槽函数
void ClientDialog::on_sendButton_clicked()
{
  //获取用户输入的消息
  QString msg = ui->messageEdit->text();
  if(msg == ""){
    return;
  }
  msg = username + ":" + msg;
  //发送消息
  tcpSocket.write(msg.toUtf8());
  //清空已输入的消息
  ui->messageEdit->clear();
}
//连接服务器按钮对应的槽函数
void ClientDialog::on_connectButton_clicked()
{
  if(status == false){//如果当前是离线状态,则连接服务器
    //获取服务器IP
    if(serverIp.setAddress(ui->serverIpEdit->text())==false){
      //critical():表示错误的消息提示框
      QMessageBox::critical(this,"Error","IP地址错误");
      return;
    }
    //获取服务器端口
    serverPort = ui->serverportEdit->text().toShort();
    if(serverPort < 1024){
      QMessageBox::critical(this,"Error","端口格式错误");
      return;
    }
    //获取聊天室昵称
    username = ui->usernameEdit->text();
    if(username == ""){
      QMessageBox::critical(this,"Error","聊天室昵称不能为空");
      return;
    }
    //向服务器发送连接请求:
    //如果成功,发送信号:connected;
    //如果失败,发送信号:error
    tcpSocket.connectToHost(serverIp,serverPort);
  }
  else{//如果当前是在线状态,则断开和服务器连接
    //向服务器发送离开聊天室的消息
    QString msg = username + ":离开了聊天室";
    //toUtf8():将QString(unicode)转换QByteArray(utf-8)
    tcpSocket.write(msg.toUtf8());
    //断开连接
    //断开后发送信号:disconnected
    tcpSocket.disconnectFromHost();
  }
}
//和服务器连接成功时执行的槽函数
void ClientDialog::onConnected(void)
{
  status = true;//设置状态标记:在线
  ui->sendButton->setEnabled(true);//恢复"发送"按钮为正常可用状态
  ui->serverIpEdit->setEnabled(false);//禁用ip输入
  ui->serverportEdit->setEnabled(false);//禁用端口输入
  ui->usernameEdit->setEnabled(false);//禁用昵称输入
  ui->connectButton->setText("离开聊天室");//修改连接服务器按钮文本
  //向服务器发送进入聊天室提示消息
  QString msg = username + ":进入了聊天室";
  //toUtf8():将QString(unicode)转换QByteArray(utf-8)
  tcpSocket.write(msg.toUtf8());
}
//和服务器断开连接时执行的槽函数
void ClientDialog::onDisconnected(void)
{
  status = false;//设置离线状态
  ui->sendButton->setEnabled(false);//禁用"发送"按钮
  ui->serverIpEdit->setEnabled(true);//恢复ip输入
  ui->serverportEdit->setEnabled(true);//恢复端口输入
  ui->usernameEdit->setEnabled(true);//恢复昵称输入
  ui->connectButton->setText("连接服务器");//修改离开聊天室按钮文本
}
//接收服务器转发聊天消息的槽函数
void ClientDialog::onReadyRead(void)
{
  //bytesAvailable():获取等待读取消息的字节数
  if(tcpSocket.bytesAvailable()){
    //读取消息
    QByteArray buf = tcpSocket.readAll();
    //显示消息到界面
    ui->listWidget->addItem(buf);
    ui->listWidget->scrollToBottom();
  }
}
//网络通信异常时执行的槽函数
void ClientDialog::onError(void)
{
  //errorString():获取网络通信异常原因的字符串
  QMessageBox::critical(this,"Error",tcpSocket.errorString());
}

main.cpp

#include "clientdialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  ClientDialog w;
  w.show();

  return a.exec();
}

最终实现效果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。