使用 QTcpSocket 和 QTcpServer 进行控制台聊天

Posted

技术标签:

【中文标题】使用 QTcpSocket 和 QTcpServer 进行控制台聊天【英文标题】:Console Chat Using QTcpSocket and QTcpServer 【发布时间】:2012-10-26 23:48:29 【问题描述】:

我想在qt框架中写一个控制台聊天程序。发送消息有问题。

客户端向服务器发送消息,但服务器在客户端程序关闭之前不会接收消息。当客户端关闭时,服务器会显示所有消息。我不希望这样。我希望服务器在我发送到时获取我的消息它。

我写了下面的代码。如果您查看客户端的主要功能,您将看到我想要做什么。

    /*

    Created BY : 
    Creation DATE : 26/10/2012

    Client interface

    */

    #ifndef CLIENT_H
    #define CLIENT_H

    #include <QtNetwork>
    #include <QObject>
    #include <QtNetwork/QTcpSocket>

    namespace NetworkArdic
    

    class Client : public QObject
    
        Q_OBJECT
        public:

            Client(QObject * obj = 0,QString add="localhost", quint16 port = 4000);


            void SendData(QString data);

            virtual ~Client();

        private slots:


            void ReadData();

            void connected();

        private:

            QTcpSocket *socket;
    ;

    

    #endif


 /*

    Created BY : 
    Creation DATE : 26/10/2012

    Client source file

    */

    #include "Client.h"
    #include <QHostAddress>
    #include <iostream>
    using namespace std;

    namespace NetworkArdic

    Client::Client(QObject * obj, QString add, quint16 port) : QObject(obj)
    

        socket = new QTcpSocket(this);


        connect(socket, SIGNAL(readyRead()), this, SLOT(ReadData()));
        connect(socket, SIGNAL(connected()), this, SLOT(connected()));

        socket->connectToHost(QHostAddress(add), port);
    

    Client::~Client()
        socket->close();
        delete socket;
    



    void Client::SendData(QString data)
    
        if(!data.isEmpty())
        
            socket->write(QString(data + "\n").toUtf8());
        
    

    void Client::ReadData()
    
        while(socket->canReadLine())
        

            QString line = QString::fromUtf8(socket->readLine()).trimmed();
            qDebug() << line;
        
    

    void Client::connected()
    
        socket->write(QString("Client : Server connection has been made (: \n").toUtf8());
    

    

    int main(int argc, char *argv[])
    
        QCoreApplication a(argc, argv);

        Client cli(0,"127.0.0.1",4000);

        string line;
        while(line!="exit")
            cout << "Message : ";
            cin >> line;
            cli.SendData(QString(line.c_str()));
        

        return a.exec();
    

     /*

    Created BY : 
    Creation DATE : 26/10/2012

    Server interface


    */

    #ifndef SERVER_H
    #define SERVER_H

    #include <QtNetwork>
    #include <QObject>
    #include <QtNetwork/QTcpServer>
    #include <QtNetwork/QTcpSocket>

    namespace NetworkArdic
    

        class Server: public QTcpServer
        

            Q_OBJECT
            public:

              Server(QObject * parent = 0 , quint16 port = 4000);
              virtual  ~Server();

            private slots:

              void acceptConnection();
              void startRead();
              void disconnected();

            private:

              QTcpSocket * client;

        ;

    

    #endif // SERVER_H



   /*

    Created BY : 
    Creation DATE : 26/10/2012

    Server source file

    */


    #include "Server.h"
    #include <iostream>
    using namespace std;

    namespace NetworkArdic

    Server::Server(QObject* parent , quint16 port): QTcpServer(parent)
    
      connect(this, SIGNAL(newConnection()),this, SLOT(acceptConnection()));

      listen(QHostAddress::Any, port );
    

    Server::~Server()
    
      delete client;
      close();
    

    void Server::acceptConnection()
    
      client = nextPendingConnection();

      connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));
      connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));

      qDebug() << "New client from:" << client->peerAddress().toString();
    

    void Server::startRead()
     
        while(client->canReadLine())
        
            QString line = QString::fromUtf8(client->readLine()).trimmed();
            qDebug() << "Client :" << line;

            client->write(QString("Server : I've taken your message (:\n").toUtf8());
        

    

    void Server::disconnected()
    

        qDebug() << "Client disconnected:" << client->peerAddress().toString();

        client->write(QString("Server : I wish you didn't leave ):\n").toUtf8());

    

    

【问题讨论】:

【参考方案1】:

写入数据后尝试使用socket->flush()。

http://doc.qt.digia.com/qt/qabstractsocket.html#flush

【讨论】:

【参考方案2】:

您使用下面的代码读取套接字数据。

void Server::startRead()
 
    while(client->canReadLine())
    
        QString line = QString::fromUtf8(client->readLine()).trimmed();
        qDebug() << "Client :" << line;

        client->write(QString("Server : I've taken your message (:\n").toUtf8());
    


我建议采用以下我测试过的代码

    while (tcp_server->hasPendingConnections()) 
        client = tcp_server->nextPendingConnection();
        client->waitForReadyRead(100);

        QByteArray  byteArray = client->readAll();
        QString s_data = byteArray.data();

        // Process s_data

        client->close();
        client->abort();
    

【讨论】:

以上是关于使用 QTcpSocket 和 QTcpServer 进行控制台聊天的主要内容,如果未能解决你的问题,请参考以下文章

Python QtNetwork.QTcpSocket.readAll() 和 QtNetwork.QTcpSocket.write() 不起作用

C++ Qt - QTcpSocket - 找不到文件

QTcpSocket重连方式

QTcpSocket 从服务器接收数据

使用 QTcpSocket 和 QTcpServer 进行控制台聊天

如何使用 QTcpSocket 获取 Protobuf 发送的数据 [重复]