• QT网络编程Tcp下C/S架构的即时通信


    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面。

    #ifndef TCPCLIENT_H
    #define TCPCLIENT_H
    
    #include <QDialog>
    #include <QListWidget>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QLabel>
    #include <QGridLayout>
    #include <QtNetWork/QHostAddress>
    #include <QtNetWork/QTcpSocket>
    
    class TcpClient : public QDialog
    {
        Q_OBJECT
    
    public:
        TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
        ~TcpClient();
    private:
        QListWidget *contentListWidget;
        QLineEdit *sendLineEdit;
        QPushButton *sendBtn;
        QLabel *userNameLabel;
        QLineEdit *userNameLineEdit;
        QLabel *serverIPLabel;
        QLineEdit *serverIPLineEdit;
        QLabel *portLabel;
        QLineEdit *portLineEdit;
        QPushButton *enterBtn;
        QGridLayout *mainLayout;
        bool status;
        int port;
        QHostAddress *serverIP;
        QString userName;
        QTcpSocket *tcpSocket;
    public slots:
        void slotEnter();
        void slotConnected();
        void slotDisconnected();
        void dataReceived();
        void slotSend();
    };
    
    #endif // TCPCLIENT_H
    

      有一个加入服务器的按钮,还有一个发送消息的按钮,在头文件,先定义两个函数。

    #include "tcpclient.h"
    #include <QMessageBox>
    #include <QHostInfo>
    
    TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f)
        : QDialog(parent,f)
    {
        setWindowTitle(tr("TCP Client"));
    
        contentListWidget = new QListWidget;
    
        sendLineEdit = new QLineEdit;
        sendBtn = new QPushButton(tr("send"));
    
        userNameLabel = new QLabel(tr("name"));
        userNameLineEdit = new QLineEdit;
    
        serverIPLabel = new QLabel(tr("server"));
        serverIPLineEdit = new QLineEdit;
    
        portLabel = new QLabel(tr("port"));
        portLineEdit = new QLineEdit;
    
        enterBtn= new QPushButton(tr("join chat"));
    
        mainLayout = new QGridLayout(this);
        mainLayout->addWidget(contentListWidget,0,0,1,2);
        mainLayout->addWidget(sendLineEdit,1,0);
        mainLayout->addWidget(sendBtn,1,1);
        mainLayout->addWidget(userNameLabel,2,0);
        mainLayout->addWidget(userNameLineEdit,2,1);
        mainLayout->addWidget(serverIPLabel,3,0);
        mainLayout->addWidget(serverIPLineEdit,3,1);
        mainLayout->addWidget(portLabel,4,0);
        mainLayout->addWidget(portLineEdit,4,1);
        mainLayout->addWidget(enterBtn,5,0,1,2);
    
        status = false;
    
        port = 8010;
        portLineEdit->setText(QString::number(port));
    
        serverIP =new QHostAddress();
    
        connect(enterBtn,SIGNAL(clicked()),this,SLOT(slotEnter()));
        connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend()));
    
        sendBtn->setEnabled(false);
    }
    
    TcpClient::~TcpClient()
    {
    
    }
    
    void TcpClient::slotEnter()
    {
        if(!status)
        {
            QString ip = serverIPLineEdit->text();
            if(!serverIP->setAddress(ip))
            {
                QMessageBox::information(this,tr("error"),tr("server ip address error!"));
                return;
            }
    
            if(userNameLineEdit->text()=="")
            {
                QMessageBox::information(this,tr("error"),tr("User name error!"));
                return;
            }
    
            userName=userNameLineEdit->text();
    
            tcpSocket = new QTcpSocket(this);
            connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
            connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
            connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    
            tcpSocket->connectToHost(*serverIP,port);
    
            status=true;
        }
        else
        {
            int length=0;
            QString msg=userName+tr(":Leave Chat Room");
            if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg. length())
            {
                return;
            }
    
            tcpSocket->disconnectFromHost();
    
            status=false;
        }
    }
    
    void TcpClient::slotConnected()
    {
        sendBtn->setEnabled(true);
        enterBtn->setText(tr("离开"));
    
        int length=0;
        QString msg=userName+tr(":Enter Chat Room");
        if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())
        {
            return;
        }
    }
    
    void TcpClient::slotSend()
    {
        if(sendLineEdit->text()=="")
        {
            return ;
        }
    
        QString msg=userName+":"+sendLineEdit->text();
    
        tcpSocket->write(msg.toLatin1(),msg.length());
        sendLineEdit->clear();
    }
    
    void TcpClient::slotDisconnected()
    {
        sendBtn->setEnabled(false);
        enterBtn->setText(tr("join chat"));
    }
    
    void TcpClient::dataReceived()
    {
        while(tcpSocket->bytesAvailable()>0)
        {
            QByteArray datagram;
            datagram.resize(tcpSocket->bytesAvailable());
    
            tcpSocket->read(datagram.data(),datagram.size());
    
            QString msg=datagram.data();
            contentListWidget->addItem(msg.left(datagram.size()));
        }
    }
    

    实现界面布局。在Enter槽函数中,确定加入还是离开的服务器的功能。如果加入了,就将消息,写到tcpsocket中,构造消。

    服务端的头文件:

    #ifndef TCPSERVER_H
    #define TCPSERVER_H
    
    #include <QDialog>
    #include <QListWidget>
    #include <QLabel>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QGridLayout>
    #include "server.h"
    
    class TcpServer : public QDialog
    {
        Q_OBJECT
    
    public:
        TcpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
        ~TcpServer();
    private:
        QListWidget *ContentListWidget;
        QLabel *PortLabel;
        QLineEdit *PortLineEdit;
        QPushButton *CreateBtn;
        QGridLayout *mainLayout;
        int port;
        Server *server;
    public slots:
        void slotCreateServer();
        void updateServer(QString,int);
    };
    
    #endif // TCPSERVER_H
    

     这是服务端的界面的,把消息显示而已。实现这个布局。

    #include "tcpserver.h"
    
    TcpServer::TcpServer(QWidget *parent,Qt::WindowFlags f)
        : QDialog(parent,f)
    {
        setWindowTitle(tr("TCP Server"));
    
        ContentListWidget = new QListWidget;
    
        PortLabel = new QLabel(tr(" port"));
        PortLineEdit = new QLineEdit;
    
        CreateBtn = new QPushButton(tr("create chat"));
        mainLayout = new QGridLayout(this);
        mainLayout->addWidget(ContentListWidget,0,0,1,2);
        mainLayout->addWidget(PortLabel,1,0);
        mainLayout->addWidget(PortLineEdit,1,1);
        mainLayout->addWidget(CreateBtn,2,0,1,2);
    
        port=8010;
        PortLineEdit->setText(QString::number(port));
    
        connect(CreateBtn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));
    }
    
    TcpServer::~TcpServer()
    {
    
    }
    
    void TcpServer::slotCreateServer()
    {
        server = new Server(this,port);
        connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));
    
        CreateBtn->setEnabled(false);
    }
    
    void TcpServer::updateServer(QString msg,int length)
    {
        ContentListWidget->addItem(msg.left(length));
    }
    

     创建TCP的套接字,以便实现服务端和客户端的通信。

    #ifndef TCPCLIENTSOCKET_H
    #define TCPCLIENTSOCKET_H
    
    #include <QtNetWork/QTcpSocket>
    #include <QObject>
    
    class TcpClientSocket : public QTcpSocket
    {
        Q_OBJECT
    public:
        TcpClientSocket();
    signals:
        void updateClients(QString,int);
        void disconnected(int);
    protected slots:
        void dataReceived();
        void slotDisconnected();
    };
    
    #endif // TCPCLIENTSOCKET_H
    

      以上是头文件,具体的是:

    #include "tcpclientsocket.h"
    
    TcpClientSocket::TcpClientSocket()
    {
        connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
        connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
    }
    
    void TcpClientSocket::dataReceived()
    {
        while(bytesAvailable()>0)
        {
            int length = bytesAvailable();
            char buf[1024];
            read(buf,length);
    
            QString msg=buf;
            emit updateClients(msg,length);
        }
    }
    
    void TcpClientSocket::slotDisconnected()
    {
        emit disconnected(this->socketDescriptor());
    }
    

      实现服务器,头文件:

    #ifndef SERVER_H
    #define SERVER_H
    
    #include <QtNetWork/QTcpServer>
    #include <QObject>
    #include "tcpclientsocket.h"
    
    class Server : public QTcpServer
    {
        Q_OBJECT
    public:
        Server(QObject *parent=0,int port=0);
        QList<TcpClientSocket*> tcpClientSocketList;
    signals:
        void updateServer(QString,int);
    public slots:
        void updateClients(QString,int);
        void slotDisconnected(int);
    protected:
        void incomingConnection(int socketDescriptor);
    };
    
    #endif // SERVER_H
    

      

    #include "server.h"
    
    Server::Server(QObject *parent,int port)
        :QTcpServer(parent)
    {
        listen(QHostAddress::Any,port);
    }
    
    void Server::incomingConnection(int socketDescriptor)
    {
        TcpClientSocket *tcpClientSocket = new TcpClientSocket;
        connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));
        connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));
    
        tcpClientSocket->setSocketDescriptor(socketDescriptor);
    
        tcpClientSocketList.append(tcpClientSocket);
    }
    
    void Server::updateClients(QString msg,int length)
    {
        emit updateServer(msg,length);
        for(int i=0;i<tcpClientSocketList.count();i++)
        {
            QTcpSocket *item = tcpClientSocketList.at(i);
            if(item->write(msg.toLatin1(),length)!=length)
            {
                continue;
            }
        }
    }
    
    void Server::slotDisconnected(int descriptor)
    {
        for(int i=0;i<tcpClientSocketList.count();i++)
        {
            QTcpSocket *item = tcpClientSocketList.at(i);
            if(item->socketDescriptor()==descriptor)
            {
                tcpClientSocketList.removeAt(i);
                return;
            }
        }
        return;
    }
    

      实现后的界面:

  • 相关阅读:
    Fiddler工具抓包
    简单Ant打包
    android中ActionBar的几个属性
    yum安装php7.2
    java 获取计算机内存
    docker apache安装
    docker 安装 openresty
    docker 安装nginx
    docker安装gitlab
    java获取时间格式
  • 原文地址:https://www.cnblogs.com/132818Creator/p/7400725.html
Copyright © 2020-2023  润新知