QT实现TCP网络聊天室

本文实例为大家分享了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;
        }
    }
}

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();
}

最终实现效果:

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

(0)

相关推荐

  • Qt实现网络聊天室的示例代码

    目录 1. 效果演示 2. 预备知识 2.1 QTcpServer 2.2 QTcpServer信号 2.3 QTcpSocket 2.4 QTcpSocket信号 3. 通信流程 3.1 服务器端 3.2 客户端 1. 效果演示 客户端 服务器 连接成功之后 2. 预备知识 在Qt中,实现网络编程的方式比用C++或C实现要方便简单许多,因为Qt已经替我们封装好了,我们会使用就可以了,然后大家还需要了解Qt 的信号槽机制,可以参考我这篇文章,Qt信号槽 2.1 QTcpServer QTcpSe

  • QT基于TCP网络聊天室

    本文实例为大家分享了QT实现网络聊天室的具体代码,供大家参考,具体内容如下 1.客户端 1.1UI设计 分两个部分,第一部分是消息区里面包含QPlainTextEdit和QListWidget,要显示接收的消息和在线的成员.第二部分QLineEdit发生字符. 1.2 子模块 1.2.1 登录界面 登录界面主要就是要有验证码,防止恶意程序的攻击.通过paintEvent画出一个白色矩形,在白色矩形里面显示四个不同颜色的字母以及随机出现的噪点. 代码: QLoginDialog.h #ifndef

  • QT实现TCP网络聊天室

    本文实例为大家分享了QT实现TCP网络聊天室的具体代码,供大家参考,具体内容如下 服务器: serverdialog.h #ifndef SERVERDIALOG_H #define SERVERDIALOG_H #include <QDialog> #include <QTcpServer> #include <QTcpSocket> #include <QDebug> #include <QTimer> namespace Ui { clas

  • QT基于TCP实现网络聊天室程序

    本文实例为大家分享了QT学习:基于TCP的网络聊天室程序,供大家参考,具体内容如下 TCP与UDP的差别如图: 一.TCP工作原理 如下图所示,TCP能够为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错 地送达网络上的其他计算机.因此,对可靠性要求高的数据通信系统往往使用TCP传输数据,但在正式收发数据前,通信双方必须首先建立连接. 二.TCP编程模型 下面介绍基于TCP的经典编程模型,TCP客户端与服务器间的交互时序如下图所示: 三.TCP服务器端编程实例 TCP服务器端的具体实现

  • 使用socket实现网络聊天室和私聊功能

    使用socket技术实现网络聊天室和私聊功能,具体内容如下 话不多说先上图: 1.聊天室群聊页面 在线用户的联系人列表 socket连接页面 私聊页面 项目介绍 与服务端实现socket连接:每个客户端连接到服务器的时候,服务器会将每个连接的socket保存在list集合中. 群聊功能:当有一个用户发送群聊消息给服务器的时候,服务器会将所有信息转发给list列表中的所有已连接的客户端. 私聊功能:用户发送私聊信息给服务器后,服务器会向一个目标ip发送消息. 显示在线联系人列表:当有新用户登录成功

  • python实现文本界面网络聊天室

    Hello大家好,今天说一下python的socket编程,基于python的socket通信的文本框网络聊天 首先,实验环境: 一个云服务器(我们这里是用的阿里云,大家将就自己的条件吧): 类Unix操作系统(如Mac OS,Linux等): Windows系列操作系统. 在这里,我使用的是阿里云,Mac OSX,Windows XP(在mac上的一个虚拟机). Server.py # -*- coding: utf-8 -*- #!/usr/local/bin/python import s

  • Python实现网络聊天室的示例代码(支持多人聊天与私聊)

    实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 vi. 使用图形界面,显示双方的语录 vii. 程序可以在一定程度上进行错误识别 概述 实验通过聊天室可以完成单人或多人之间的聊天通信,功能的实现主要是通过Socket通信来实现.本次实验采用客户端/服务器(C/S)架构模式,通过Python语言来编写服务器端与客户端的程序.运用多线程可完成多点对多

  • C++基于socket多线程实现网络聊天室

    本文实例为大家分享了C++基于socket多线程实现网络聊天室的具体代码,供大家参考,具体内容如下 1. 实现图解 2. 聊天室服务端:TCP_Server_Chat.cpp #include <winsock2.h> // winsock2的头文件 #include <iostream> #pragma comment(lib, "ws2_32.lib") using namespace std; // stdcall的线程处理函数 DWORD WINAPI

  • C++实现简易UDP网络聊天室

    本文实例为大家分享了C++实现简易UDP网络聊天室的具体代码,供大家参考,具体内容如下 工程名:NetSrv NetSrv.cpp //服务器端 #include<Winsock2.h> #include<stdio.h> void main() { //加载套接字库 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1,1); err = WSAStartup(wVersi

  • C语言实现简易网络聊天室

    本文实例为大家分享了C语言实现网络聊天室的具体代码,供大家参考,具体内容如下 业务逻辑: 1.客户端注册名字 2.告诉所有在线的客户端,XXX进入聊天室 3.新建一个线程为该客户端服务,随时接收客户端发送来的消息 4.当接收到一个客户端的消息时,向每一个客户端转发一份(群聊) 5.同时在线人数最多50人 任何客户端可以随意随时进入或退出客户端 服务端代码server.c #include <stdio.h> #include <stdlib.h> #include <stri

随机推荐