Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 断开Qt后连接到服务器时客户端程序崩溃_C++_Qt_Tcp Ip_Qtcpsocket - Fatal编程技术网

C++ 断开Qt后连接到服务器时客户端程序崩溃

C++ 断开Qt后连接到服务器时客户端程序崩溃,c++,qt,tcp-ip,qtcpsocket,C++,Qt,Tcp Ip,Qtcpsocket,我正在基于Qt实现TCP Ip服务器的客户端,但当我关闭连接并点击connect按钮重新启动时,程序崩溃 项目概述。我有Qwidget(主应用程序),带有2行编辑功能,用户可以输入端口号和服务器Ip地址。 它还有两个按钮,分别连接到服务器和断开连接。点击connect按钮,它将调用客户端套接字的构造函数并调用connectToHost 测试:尝试在同一台计算机上进行测试,服务器在端口6000和ip地址127.0.0.1上运行 问题:当我启动客户端应用程序,输入端口号和地址,点击连接按钮,它成功连

我正在基于Qt实现TCP Ip服务器的客户端,但当我关闭连接并点击connect按钮重新启动时,程序崩溃

项目概述。我有Qwidget(主应用程序),带有2行编辑功能,用户可以输入端口号和服务器Ip地址。 它还有两个按钮,分别连接到服务器和断开连接。点击connect按钮,它将调用客户端套接字的构造函数并调用connectToHost

测试:尝试在同一台计算机上进行测试,服务器在端口6000和ip地址127.0.0.1上运行

问题:当我启动客户端应用程序,输入端口号和地址,点击连接按钮,它成功连接。我可以成功地写入服务器。然后,我单击“断开连接”按钮,它成功地断开连接,但之后,如果我再次单击“连接”按钮进行连接,它将崩溃。我知道问题出在tcpSocket上,但不知道如何解决它

clientAgent(QWidget应用程序).h

ClientAgent.cpp

ClientAgent::ClientAgent( QWidget *parent ) :
          QWidget(parent),
          ui( new Ui::ClientAgent )
{

// Widget declartion and initilisation
// Layout design etc

   //define signals and slots for Client
  // signals and slots

  connect( btnStartClient,  SIGNAL( clicked() ), this, SLOT( startClient() ) );
  connect( btnStopClient,   SIGNAL( clicked() ), this, SLOT( stopClient() ) );

// for write
connect( lEditCliReq,  SIGNAL( textChanged(const QString& ) ), this, SLOT( getCliReqTextChanged() ) );

  ui->setupUi( this );

}

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


void ClientAgent::startClient()
{
  qDebug() << " we are in strt Clinet";
  qDebug() << " connecting ";

  // get server address and port number from GUI

  QString testAddr = lEditAddr->text();
  QString testPort = lEditPrt->text();

  tcpSockForTest = new ClientForTest( testAddr, testPort.toInt(), this );

  if( tcpSockForTest->connectToServer() == true )
   {
      lblCliStatus->setText(" connected ....");
   }
  else
   {
      lblCliStatus->setText(" failed to connect....");
   }

}

void ClientAgent::stopClient()
{
  qDebug() << " disconnecting ";
  tcpSockForTest->disconnectToServer();
  delete tcpSockForTest;
}
ClientForTest.cpp

ClientForTest::ClientForTest( QString hostAddr, quint16 portNum, QObject *parent ) :
                            hostName( hostAddr ),
                            portNumber( portNum ),
                            QObject( parent )
{
  connect( sockFortest, SIGNAL( connected() ), this, SLOT( connectedToTest() ) );
  connect( sockFortest, SIGNAL( disconnected() ), this, SLOT( connectionClosedByServer() ) );
  connect( sockFortest, SIGNAL( error( QAbstractSocket::SocketError ) ), this, SLOT( error() ) );

  storeLineEditMsg = "";
}
void ClientForTest::executeSignals()
{
// actually I need toplace itin constructor will do later on
 connect( this,  SIGNAL( sigSendData() ), this, SLOT( connectedToTest() ) );
}

ClientForTest::~ClientForTest()
{

  sockFortest->close();
  delete sockFortest;
}

bool ClientForTest::connectToServer()
{
  sockFortest = new QTcpSocket( this->parent() ); // COULD be Probelm here but how to fix it?
  sockFortest->connectToHost( hostName, portNumber );
  nextBlockSize = 0;
  executeSignals();
  return sockFortest->waitForConnected(1000);
}

void ClientForTest::disconnectToServer()
{
  sockFortest->close();
  //sockFortest.close();
  qDebug() << "in disconnect for Test ";
  emit updateLabelinParent( updateStatusDis );
}


void ClientForTest::connectionClosedByServer()
{

  qDebug() << "connection closed by server ";
  if( nextBlockSize != 0xFFFF )
  {
    disconnectToServer();
  }
}

void ClientForTest::error()
{
  qDebug() << "in error ";
  disconnectToServer();
}

void ClientForTest::writeToTest( const QString& stripCmd )
{
  storeLineEditMsg = stripCmd;
  if( sockFortest->state() == QTcpSocket::UnconnectedState )
  {
      sockFortest->close();
      delete sockFortest; 
      sockFortest = new QTcpSocket( this->parent() );
      if( connectToServer() == true )
      {
         qDebug() << " YEEEE CONNECTED AGAIN finally ";
      }
  }
  if( sockFortest->state() == QTcpSocket::ConnectedState )
   {
      qDebug() << " YEEEE CONNECTED";
      sigSendData();
   }
}


void ClientForTest::connectedToTest( )
{
  QByteArray block;
  QDataStream out( &block, QIODevice::WriteOnly );

  out.setVersion( QDataStream::Qt_4_3 );

  QString stripCmd = getStoreMsgFrmCliReq(); // received info for some other function I havnt shown that func here

   out << quint16( 0 ) << stripCmd;

  out.device()->seek( 0 );

  out << quint16( block.size() - sizeof( quint16 ) );

  qDebug()<<" yeeeee connected state...";

  sockFortest->write( block );

  //reset storeLineEditMessage
  storeLineEditMsg.clear();
}
ClientForTest::ClientForTest(QString hostAddr、quint16 portNum、QObject*parent):
主机名(hostAddr),
端口号(portNum),
QObject(父对象)
{
连接(sockFortest,信号(connected()),此,插槽(connectedToTest());
连接(sockFortest,信号(disconnected()),此,插槽(connectionClosedByServer());
连接(sockFortest,信号(error(QAbstractSocket::socketterror)),此,插槽(error());
storeLineEditMsg=“”;
}
void ClientForTest::executeSignals()
{
//事实上,我需要把它放在后面的构造函数中
连接(此,信号(sigSendData()),此,插槽(connectedToTest());
}
ClientForTest::~ClientForTest()
{
sockFortest->close();
删除sockFortest;
}
boolclientfortest::connectToServer()
{
sockFortest=new QTcpSocket(this->parent());//这里可能有问题,但如何解决?
sockFortest->connectToHost(主机名、端口号);
nextBlockSize=0;
executeSignals();
返回sockFortest->waitForConnected(1000);
}
void ClientForTest::disconnectToServer()
{
sockFortest->close();
//sockFortest.close();
qDebug()父对象();
if(connectToServer()==true)
{
qDebug()状态()==QTcpSocket::ConnectedState)
{

qDebug()有几件事可能是导致崩溃的原因:

  • 您连接了
    ClientForTest
    构造函数内的信号,但套接字本身是稍后创建的。这将不起作用。在连接之前,将行
    sockFortest=new qtcsocket(this);
    移动到构造函数
  • 同一行,使用
    this
    代替
    this->parent()
  • 最后:您可以在多个位置创建/删除套接字。不要这样做。在构造函数中创建套接字,并将
    this
    作为父项,就是这样。在
    connectToServer
    中,建立连接,然后在
    disconnectToServer
    中,使用
    disconnectFromHost
    关闭它。也一样de>startClient
stopClient
。创建对象一次,只需使用连接/断开连接功能,无需删除 如果需要代码,我可以添加一些

由于有人提出要求,这里有更多的解释:

  • 当然,您可以使用parent,但是在您的情况下,
    ClientForTest
    也是一个
    QObject
    。如果您将
    ClientForTest
    设置为套接字的父项,将小部件设置为
    ClientForTest
    的父项,它们都将被正确清理。如果您使用
    this->parent()
    ,两者都将被销毁“同时”。但是,一个先到,有时Qt会更改顺序,因此您的套接字可能会在
    ClientForTest
    之前被销毁。
    ClientForTest
    的析构函数会崩溃。如果套接字是
    ClientForTest
  • close()
    disconnectFromHost()
    之间的主要区别在于第一个实际关闭了操作系统套接字,而第二个没有。问题是,套接字关闭后,您无法使用它来创建新连接。因此,如果要重用套接字,请使用
    disconnectFromHost()
    否则
    close()
  • 关于第3条和第4条:
    您所做的是在用户单击connect时创建
    ClientForTest
    ,并在单击disconnect时将其删除。但这不是一个好的设计(IMHO)。由于
    tcpSockForTest
    已经是类的一员,所以在构造函数中创建它(通过new),然后在析构函数中删除它(可选,因为如果您将小部件作为父部件传递,Qt将为您删除它)。

    您调试过应用程序以查看它在哪一行崩溃吗?@BowDzone,是的,它在的构造函数中崩溃ClientForTest@Bowdzone,如果我将构造函数中定义的所有连接都带到函数executeSignals()它工作得很好。但是现在我想知道我添加了太多的delete和new调用。有更好的方法吗?您不必每次断开连接时都删除
    qtcsocket
    对象,每次连接时都创建它的新实例。只需在构造函数中初始化一个实例即可。但是问题是似乎是您的
    ClientForTest
    构造函数。您连接了
    sockFortest
    对象的信号,但此对象尚未初始化。您正在使用未初始化的指针。正是如此。每次建立新连接时,您都会创建一个新的
    qtcsocket
    对象。断开连接时,您会删除该对象t、 我不知道您的应用程序到底是如何工作的,但它似乎没有必要。您只需在构造函数中创建一次
    qtcsocket
    对象,然后使用该实例。
    qtcsocket
    QObject的子类<
    
    class ClientForTest : public QObject
    {
      Q_OBJECT
    public:
      ClientForTest( QString hostAddr, quint16 portNum, QObject *parent );
    
      bool connectToServer();
      void disconnectToServer();
      QString getStoreMsgFrmCliReq( ) const;
    
      void writeToTest(const QString& stripCmd );
      void executeSignals();
    
        ~ClientForTest();
    
    signals:
      void sigSendData();
    
    public slots:
      void connectedToTest();
      void connectionClosedByServer();
      void error();
    
    private:
       QTcpSocket   *sockFortest;
       QString       hostName;
       quint16       portNumber;
       quint16       nextBlockSize;
       QString       storeLineEditMsg;// store message from lineEditCliReq;
    
      };
    
    ClientForTest::ClientForTest( QString hostAddr, quint16 portNum, QObject *parent ) :
                                hostName( hostAddr ),
                                portNumber( portNum ),
                                QObject( parent )
    {
      connect( sockFortest, SIGNAL( connected() ), this, SLOT( connectedToTest() ) );
      connect( sockFortest, SIGNAL( disconnected() ), this, SLOT( connectionClosedByServer() ) );
      connect( sockFortest, SIGNAL( error( QAbstractSocket::SocketError ) ), this, SLOT( error() ) );
    
      storeLineEditMsg = "";
    }
    void ClientForTest::executeSignals()
    {
    // actually I need toplace itin constructor will do later on
     connect( this,  SIGNAL( sigSendData() ), this, SLOT( connectedToTest() ) );
    }
    
    ClientForTest::~ClientForTest()
    {
    
      sockFortest->close();
      delete sockFortest;
    }
    
    bool ClientForTest::connectToServer()
    {
      sockFortest = new QTcpSocket( this->parent() ); // COULD be Probelm here but how to fix it?
      sockFortest->connectToHost( hostName, portNumber );
      nextBlockSize = 0;
      executeSignals();
      return sockFortest->waitForConnected(1000);
    }
    
    void ClientForTest::disconnectToServer()
    {
      sockFortest->close();
      //sockFortest.close();
      qDebug() << "in disconnect for Test ";
      emit updateLabelinParent( updateStatusDis );
    }
    
    
    void ClientForTest::connectionClosedByServer()
    {
    
      qDebug() << "connection closed by server ";
      if( nextBlockSize != 0xFFFF )
      {
        disconnectToServer();
      }
    }
    
    void ClientForTest::error()
    {
      qDebug() << "in error ";
      disconnectToServer();
    }
    
    void ClientForTest::writeToTest( const QString& stripCmd )
    {
      storeLineEditMsg = stripCmd;
      if( sockFortest->state() == QTcpSocket::UnconnectedState )
      {
          sockFortest->close();
          delete sockFortest; 
          sockFortest = new QTcpSocket( this->parent() );
          if( connectToServer() == true )
          {
             qDebug() << " YEEEE CONNECTED AGAIN finally ";
          }
      }
      if( sockFortest->state() == QTcpSocket::ConnectedState )
       {
          qDebug() << " YEEEE CONNECTED";
          sigSendData();
       }
    }
    
    
    void ClientForTest::connectedToTest( )
    {
      QByteArray block;
      QDataStream out( &block, QIODevice::WriteOnly );
    
      out.setVersion( QDataStream::Qt_4_3 );
    
      QString stripCmd = getStoreMsgFrmCliReq(); // received info for some other function I havnt shown that func here
    
       out << quint16( 0 ) << stripCmd;
    
      out.device()->seek( 0 );
    
      out << quint16( block.size() - sizeof( quint16 ) );
    
      qDebug()<<" yeeeee connected state...";
    
      sockFortest->write( block );
    
      //reset storeLineEditMessage
      storeLineEditMsg.clear();
    }