Повторная попытка клиента c ++ (sys / socket.h) подключиться к серверу приводит к ошибке сегмента - PullRequest
0 голосов
/ 30 октября 2019

Решено Благодаря комментарию пользователя 4581301 я начал проверять все unique_ptr и обнаружил, что std :: unique_ptr был неправильным в деструкторе.

Исходное сообщение:

(извиняюсь за мой плохой английский)

Я строю систему клиентского <-> сервера в c ++ с "sys / socket", где "пользователь" запускает сервери клиенты будут работать "всегда".

Я имею в виду, что клиент будет пытаться подключиться к серверу через определенные промежутки времени независимо от того, запущен он или нет. Однако, когда я делаю это, происходит ошибка сегментации на третьей попытке подключиться к серверу. (Да, это, вероятно, плохой дизайн сервер-клиент).

, потому что сервер не нужен в этом кенарио, только часть клиента показана возлюбленной:client.cpp ()

int main(){
  int port = 8888;
  std::string adr = "127.0.0.1";
  bool run = true
  std::unique_ptr<socketHandler> con;

  while(run){
     con.reset(new socketHandler(adr, port));
     while(con->connected()){
       // do stuff
     }
  }
}

class socketHandler{
public:
   socketHandller(std::string address, int port):
   incommingMessageHandler(new MessageHandler())
    , portNummer(port)
    , address(address)
   {
      if( (this->socketContainer = socket(AF_INET, SOCK_STREAM, 0)) < 0){
         exit(1);
      }

      memset(&this->servAddr, '0', sizeof(this->servAddr));
      this->servAddr.sin_family = AF_INET;
      this->servAddr.sin_port = htons(this->portNummer);

      if( inet_pton(AF_INET, this->address.c_str(), &this->servAddr.sin_addr) <= 0){
         exit(1);
      }

      /**
       * The third time this "connect" is "excuted" I get seg fault
       * if it failed on the two first. It does not even call the 
       * "closeSocket" function.
      */
      if(connect(this->socketContainer, (struct sockaddr*)&this->servAddr, sizeof(this->servAddr)) < 0){
         closeSocket();
         return; 
      }

      // More stuff
   }

   bool connected(){
     // return true if "test-message" been received from server.
   }

   // skiped some functions as well

private:
    void closeSocket(){
       close(this->socketContainer);
       this->socketContainer = 0;
    }

   int portNummer;
   std::string address;
   std::atomic<int> socketContainer;
   struct sockaddr_in servAddr;
   std::atomic<bool> connectStatus;
}

Я чувствую, что это был единственный "код", имеющий проблему с тем, чтобы не все было, я дам больше, если необходимо.

Отто, что я нашел с точки зрения документации, я чувствую, где потеряно, и то, что я нашел во всех онлайн-примерах на sys / socket, все они для Exit (1) при неудачном вызове «connect ()», но никакой реальной причины почему.

Кто-нибудь здесь знает, почему это происходит? И / или есть способ «исправить» эту проблему?

Некоторые ссылки: - https://linux.die.net/man/2/connect - https://www.geeksforgeeks.org/socket-programming-cc/ - http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/

Спасибо за вашу помощь.

Решение:

конфиденциально (деструктор ошибки сегмента):

int main(){
  int port = 8888;
  std::string adr = "127.0.0.1";
  bool run = true
  std::unique_ptr<socketHandler> con;

  while(run){
     con.reset(new socketHandler(adr, port));
     while(con->connected()){
       // do stuff
     }
  }
}

class socketHandler{
public:
   socketHandller(std::string address, int port):
   incommingMessageHandler(new MessageHandler())
    , portNummer(port)
    , address(address)
   {
      if( (this->socketContainer = socket(AF_INET, SOCK_STREAM, 0)) < 0){
         exit(1);
      }

      memset(&this->servAddr, '0', sizeof(this->servAddr));
      this->servAddr.sin_family = AF_INET;
      this->servAddr.sin_port = htons(this->portNummer);

      if( inet_pton(AF_INET, this->address.c_str(), &this->servAddr.sin_addr) <= 0){
         exit(1);
      }

      /**
       * The third time this "connect" is "excuted" I get seg fault
       * if it failed on the two first. It does not even call the 
       * "closeSocket" function.
      */
      if(connect(this->socketContainer, (struct sockaddr*)&this->servAddr, sizeof(this->servAddr)) < 0){
         closeSocket();
         return; 
      }

      msgRecvThrd.reset(new std::thread(&ClientSocketHandler::receiveMessagesFromSocket, this));
   }

   bool connected(){
     // return true if "test-message" been received from server.
   }

   void receiveMessagesFromSocket(){
      // if incomming message add the messagehandler... (while thread running)
   }

   ~socketHandller(){
      /**
      * THIS CAUSED THE SEG FAULT (obviouse, when thinking about it)
      */
      while(true){
         if(this->msgRecvThrd->joinable()){
           this->msgRecvThrd->join();
           break;
         }
      }
   }


   // skiped some functions as well

private:
    void closeSocket(){
       close(this->socketContainer);
       this->socketContainer = 0;
    }

   int portNummer;
   std::string address;
   std::atomic<int> socketContainer;
   struct sockaddr_in servAddr;
   std::atomic<bool> connectStatus;
   std::unique_ptr<MessageHandler> incommingMessageHandler;
   std::unique_ptr<std::thread> msgRecvThrd;
}

Деструктор, который исправил ошибку сегмента:

int main(){
  int port = 8888;
  std::string adr = "127.0.0.1";
  bool run = true
  std::unique_ptr<socketHandler> con;

  while(run){
     con.reset(new socketHandler(adr, port));
     while(con->connected()){
       // do stuff
     }
  }
}

class socketHandler{
public:
   socketHandller(std::string address, int port):
   incommingMessageHandler(new MessageHandler())
    , portNummer(port)
    , address(address)
   {
      if( (this->socketContainer = socket(AF_INET, SOCK_STREAM, 0)) < 0){
         exit(1);
      }

      memset(&this->servAddr, '0', sizeof(this->servAddr));
      this->servAddr.sin_family = AF_INET;
      this->servAddr.sin_port = htons(this->portNummer);

      if( inet_pton(AF_INET, this->address.c_str(), &this->servAddr.sin_addr) <= 0){
         exit(1);
      }

      /**
       * The third time this "connect" is "excuted" I get seg fault
       * if it failed on the two first. It does not even call the 
       * "closeSocket" function.
      */
      if(connect(this->socketContainer, (struct sockaddr*)&this->servAddr, sizeof(this->servAddr)) < 0){
         closeSocket();
         return; 
      }

      msgRecvThrd.reset(new std::thread(&ClientSocketHandler::receiveMessagesFromSocket, this));
   }

   bool connected(){
     // return true if "test-message" been received from server.
   }

   void receiveMessagesFromSocket(){
      // if incomming message add the messagehandler... (while thread running)
   }

   ~socketHandller(){
      /**
      * FIXED
      */
      while(this->msgRecvThrd != nullptr){
         if(this->msgRecvThrd->joinable()){
           this->msgRecvThrd->join();
           this->msgRecvThrd.reset();
         }
      }
   }


   // skiped some functions as well

private:
    void closeSocket(){
       close(this->socketContainer);
       this->socketContainer = 0;
    }

   int portNummer;
   std::string address;
   std::atomic<int> socketContainer;
   struct sockaddr_in servAddr;
   std::atomic<bool> connectStatus;
   std::unique_ptr<MessageHandler> incommingMessageHandler;
   std::unique_ptr<std::thread> msgRecvThrd;
}
...