提高客户端 - 服务器连接稳定性

时间:2014-10-30 22:40:59

标签: c++ boost tcp

我在设置客户端 - 服务器连接方面很新,我遇到了在两台计算机之间发送数据的问题。我的代码运行良好,#34; localhost"但是有两台计算机通过网络,它会在某处崩溃。在localhost中,我可以传输22 MB数据,这是我最大的数据文件。

对于两台计算机的连接: 我有一个小例子来传输数据,它的数据量大约是11 kb。这个例子在这里也运作良好。然而,下一个更大的例子,大小为0f 230 kb崩溃。

我正在使用同步TCP。

SERVER:

  try
  {
    boost::asio::io_service io_service;
    tcp::acceptor acceptor( io_service, tcp::endpoint( tcp::v4( ), 40986 ) );
    CDBReader* sender = CDBReader::getInstance( );
    for ( ;; )
    {
       tcp::socket socket( io_service );
       mySocket = &socket;
       acceptor.accept( *mySocket );
  }

客户端:

try
{
 boost::asio::io_service io_service;
 tcp::resolver resolver( io_service );
 tcp::resolver::query query( serverName, "40986" );
 tcp::resolver::iterator endpoint_iterator = resolver.resolve( query );
 tcp::socket socket( io_service );
 mySocket = &socket;
 boost::asio::connect( *mySocket, endpoint_iterator );
 boost::system::error_code error;
}

这是我创建连接的方式。

这是我在Server中用来发送数据的功能。根据数据量,我分成几部分后发送。

void vtkCDBConnectorSource::sendString( std::string message )
{
  std::cout << "I am in sendString" << std::endl;
  int loopCounter = message.size() / charArraySize + 1;
  size_t mSize = message.size();

  std::stringstream SStream;
  SStream << loopCounter;
  std::string noLoop = SStream.str( );
  //  std::cout << "loopCounter = " << loopCounter << std::endl;
 if(loopCounter >= 10 && loopCounter < 100)
 {
   std::stringstream digitNumberSizeStream;
   digitNumberSizeStream << 2;
   std::string digitNumberSize = digitNumberSizeStream.str( );
   digitNumberSizeStream.str(std::string());
   digitNumberSizeStream.clear();
   //   std::cout << "digitNumberSize = " << digitNumberSize << std::endl;
   //   std::cout << "noLoop = " << noLoop << std::endl;

   size_t s10 = mySocket->send( boost::asio::buffer( digitNumberSize ) );
   size_t s11 = mySocket->send( boost::asio::buffer( noLoop ) );
 }
 else if( loopCounter >= 100 && loopCounter < 1000)
 {
   std::stringstream digitNumberSizeStream;
   digitNumberSizeStream << 3;
   std::string digitNumberSize = digitNumberSizeStream.str( );
   digitNumberSizeStream.str(std::string());
   digitNumberSizeStream.clear();
   //    std::cout << "digitNumberSize = " << digitNumberSize << std::endl;
   //    std::cout << "noLoop = " << noLoop << std::endl;

  size_t s10 = mySocket->send( boost::asio::buffer( digitNumberSize ) );
  size_t s11 = mySocket->send( boost::asio::buffer( noLoop ) );
 }
 else if( loopCounter >= 1000)
 {
   std::stringstream digitNumberSizeStream;
   digitNumberSizeStream << 4;
   std::string digitNumberSize = digitNumberSizeStream.str( );
   digitNumberSizeStream.str(std::string());
   digitNumberSizeStream.clear();
  //    std::cout << "digitNumberSize = " << digitNumberSize << std::endl;
  //    std::cout << "noLoop = " << noLoop << std::endl;

 size_t s10 = mySocket->send( boost::asio::buffer( digitNumberSize ) );
 size_t s11 = mySocket->send( boost::asio::buffer( noLoop ) );
}
else
{
   std::stringstream digitNumberSizeStream;
   digitNumberSizeStream << 1;
   std::string digitNumberSize = digitNumberSizeStream.str( );
   digitNumberSizeStream.str(std::string());
   digitNumberSizeStream.clear();

   //   std::cout << "digitNumberSize = " << digitNumberSize << std::endl;
   //   std::cout << "noLoop = " << noLoop << std::endl;

   size_t s10 = mySocket->send( boost::asio::buffer( digitNumberSize ) );
   size_t s11 = mySocket->send( boost::asio::buffer( noLoop ) );
  }
 SStream.str( std::string( ) );
 SStream.clear( );

  int i = 0;
  while( i < loopCounter )
  {
     int secLoop = 0;
     if( mSize >= charArraySize)
  {
      secLoop = charArraySize;
      mSize = mSize - secLoop;
   }
   else
   {
     secLoop = mSize;
   }

   std::string tempMessage;
   for( size_t j=0; j<secLoop; j++)
   {
     tempMessage.push_back( message[charArraySize*i + j] );
   }

   std::stringstream messageSizeStream;
   messageSizeStream << secLoop;

   std::string messageSize = messageSizeStream.str( );
   size_t dataDigitSize = messageSizeStream.str().size();
   std::stringstream messageDigitStream;
   messageDigitStream << dataDigitSize;

   std::string messageDigit = messageDigitStream.str( );

   // std::cout << "messageDigit = " << messageDigit << std::endl;
   //    std::cout << "messageSize = " << messageSize << std::endl;

  size_t s12 = mySocket->send( boost::asio::buffer( messageDigit ) );
  size_t s13 = mySocket->send( boost::asio::buffer( messageSize ) );
  size_t s14 = mySocket->send( boost::asio::buffer( tempMessage ) );
  messageSizeStream.str( std::string( ) );
  messageSizeStream.clear( );
  ++i;
}

//  std::cout<<"SendString Finished"<<std::endl;
mySendStream.str( std::string( ) );
mySendStream.clear( );
}

这是客户端接收数据的功能:

size_t vtkCDBConnectorSource::DataContainer( )
{
   std::cout << "I am in DataContainer" << std::endl;
   char* sizeOfLoop = new char[10];
   char* noOfLoops= new char[100];

   size_t dataLength;
   size_t loopsizeDigit = mySocket->receive( boost::asio::buffer( sizeOfLoop, 1 ) );
   std::stringstream lStream;
   lStream << sizeOfLoop;
   size_t numberOfloops;
   lStream >> numberOfloops ;
   lStream.str(std::string());
   lStream.clear();
   std::cout<<"Number of Digits for Loops= "<<numberOfloops<<std::endl;
  size_t sizeDigit = mySocket->receive( boost::asio::buffer(noOfLoops,     numberOfloops   ) );

   std::stringstream RStream;
   RStream << noOfLoops;

   size_t loopSize;
   RStream >> loopSize ;
   RStream.str(std::string());
   RStream.clear();
   std::cout << "loopSize = " << loopSize << std::endl;

   int i = 0;
   while( i < loopSize )
   {
    char* dataDigit= new char[100];
    size_t sizeDataDigit = mySocket->receive( boost::asio::buffer( dataDigit, 1 ) );

    RStream << dataDigit;
    size_t digitNumber;
    RStream >> digitNumber;
    RStream.str(std::string());
    RStream.clear();
    char* dataSize = new char[100];
   //    std::cout << "digitNumber = " << digitNumber << std::endl;
   size_t sizeData = mySocket->receive( boost::asio::buffer( dataSize, digitNumber ) );

   RStream << dataSize;
   size_t dataAmount;
   RStream >> dataAmount;
   RStream.str(std::string());
   RStream.clear( );

   char* data= new char[100000];
   //    std::cout << "dataAmount = " << dataAmount << std::endl;

   dataLength = mySocket->receive( boost::asio::buffer( data, dataAmount ) );

   std::cout << "dataLength = " << dataLength << std::endl;

   int k = 0;

   while ( dataLength-- > 0 ) // maybe need to divide by 2
   {
     myReceivedStream << data[k++];
   }

   delete[] data;
   delete[] dataDigit;
   delete[] dataSize;
   ++i;
   }
   delete[] sizeOfLoop;
   delete[] noOfLoops;
    std::cout << " ---- Data Container FINISHED--- " << std::endl;
    return dataLength;
 }

我希望我可以告诉我的问题,如果有任何不清楚的地方,请告诉我。 提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

此代码是未定义的行为:

tcp::socket socket( io_service );
mySocket = &socket;

您正在tcp::socket块的范围内创建try,然后将其存储在mySocket中,该地址位于此范围之外。离开try块后,tcp::socket将被销毁,mySocket仍然指向已销毁的对象。

它可能会工作一段时间,直到某些其他代码运行并覆盖被破坏的tcp::socket对象所占用的堆栈部分。

解决此问题后,同样的问题也适用于您的io_service;你使用对它的引用构造套接字,然后允许它被销毁,所以固定的tcp::socket对象仍然保持对被破坏的io_service的引用。