openigtlink / OpenIGTLink

Free, open-source network communication library for image-guided therapy
http://openigtlink.org
BSD 3-Clause "New" or "Revised" License
103 stars 184 forks source link

socket::GetConnected() and socket::IsNotNull() Are Not Detecting Dropped Client Connections #173

Closed pacarvalho closed 6 years ago

pacarvalho commented 6 years ago

We are running an OpenIGT Link Server on an sbRIO-9651 module running real time linux and we are running into an issue when the following steps are taken:

  1. Server is started.
  2. Client connects to server.
  3. Client is turned off (disconnects from server).
  4. Client attempts to reconnect to server.

In the above scenario the OpenIGT link server never detects that the client dropped. Status remains "Connected" all throughout which impedes the client from connecting again and receiving data.

The value of IsNotNull before connecting is false. The value of IsNotNull after connecting is true even when the client disconnects. The same applies for GetConnected.

The return value for socket::Receive() is 0 when the client has disconnected and -1 when the client is connected and no data is received.


while (1) {
  // Check if we can connect on the client socket
  igtModule->socket = serverSocket->WaitForConnection(1000);
  igtModule->_robot->_socketIGTConnection = "Listening";

  // If we were able to connect to the client socket
  if (igtModule->socket.IsNotNull() && igtModule->socket->GetConnected()) {
  igtModule->_robot->_socketIGTConnection = "Connected";

    // Create a message buffer to receive header
    igtl::MessageHeader::Pointer headerMsg;
    headerMsg = igtl::MessageHeader::New();

    // Allocate a time stamp
    igtl::TimeStamp::Pointer ts;
    ts = igtl::TimeStamp::New();

    // While we're connected to the the client socket
    while (igtModule->socket.IsNotNull() && igtModule->socket->GetConnected()) {

      // Initialize receive buffer
      headerMsg->InitPack();

      // Receive generic header from the socket
      cout << "Before receive" << endl;
      igtModule->socket->SetReceiveTimeout(10000) 
      int r = igtModule->socket->Receive(headerMsg->GetPackPointer(),headerMsg->GetPackSize());
    }
  }
}
leochan2009 commented 6 years ago

Thanks for reporting!, will work on the issue ASAP!

leochan2009 commented 6 years ago

Hi,

I think the workflow of your program is not correct, the inner while loop should not depending on the status of igtlModule->socket. Would you please try:

while (1) {
  // Check if we can connect on the client socket
  igtModule->socket = serverSocket->WaitForConnection(1000);
  igtModule->_robot->_socketIGTConnection = "Listening";
  // If we were able to connect to the client socket
  if (igtModule->socket.IsNotNull() && igtModule->socket->GetConnected()) {
    igtModule->_robot->_socketIGTConnection = "Connected";
    // Create a message buffer to receive header
    igtl::MessageHeader::Pointer headerMsg;
    headerMsg = igtl::MessageHeader::New();
    // Allocate a time stamp
    igtl::TimeStamp::Pointer ts;
    ts = igtl::TimeStamp::New();
    // While we're connected to the the client socket
    for (; ;)  
    {
       // Initialize receive buffer
       headerMsg->InitPack();
       // Receive generic header from the socket
       cout << "Before receive" << endl;
      igtModule->socket->SetReceiveTimeout(10000) 
      int r = igtModule->socket->Receive(headerMsg->GetPackPointer(),headerMsg->GetPackSize());
      if (r == 0)
       {
          std::cerr << "Disconnecting the client." << std::endl;
          igtModule->socket->CloseSocket();
          break;
       }   
    }
  }
}

Also, you could refer the example code for more information: TrackingDataServer

Let me know if the modification works for your platform, thanks Best, Longquan

pacarvalho commented 6 years ago

That worked! We were following another example which appears to not have been implemented with the reconnecting in mind.

leochan2009 commented 6 years ago

Great to hear that it worked!