문제

I'm working on win ce 6 modbus tcp client server, application is developed for a client server communication and it is working fine. now req is my slave device should respond to the diff slave addresses polled by master/client. Can I just change slave id and establish connection or I need to close previous connection and again establish new one

below is the code, which is working fine for one node, if I polled with other node ID then it gives exception. what change it req to communicate with other node simultaneously. My device should be able to communicate with 32 diff nodes on modbus tcp. Shall I create individual threads for each node but how they will communicate on same port? before establishing connection with other node shall I close previous node?

startupServer(int slaveAddr,  const TCHAR * const hostName)
{

   int result;
   int tcpOption;
   struct sockaddr_in hostAddress;

   if (isStarted())
      return (FTALK_ILLEGAL_STATE_ERROR);

   // Note: For TCP we allow 0 as slave address, -1 means ignore slave adr
   if ((slaveAddr < -1) || (slaveAddr > 255))
      return (FTALK_ILLEGAL_ARGUMENT_ERROR);
   this->slaveAddr = slaveAddr;

   //
   // Special treatment for the Win32 platform, needs to load WinSock DLL
   //
#ifdef _WINSOCKAPI_
   WSADATA wsaData;

   result = WSAStartup(0x0101, &wsaData);
   if (result != 0)
      return (FTALK_SOCKET_LIB_ERROR);
#endif

   //
   // Open socket
   //
   listenSocket = socket(PF_INET, SOCK_STREAM, 0);
   if (listenSocket == INVALID_SOCKET)
   {
      shutdownServer();
      return (FTALK_OPEN_ERR);
   }

   //
   // Configure listen socket options (we ignore errors here)
   //
#ifdef SO_REUSEADDR
   tcpOption = 1; // Enable option
   setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR,
              (char *) &tcpOption, sizeof (tcpOption));
#endif

   //
   // Binding the listen socket to the port
   //
   hostAddress.sin_family = AF_INET;
   if ((hostName == NULL) || (hostName[0] == '\0'))
      hostAddress.sin_addr.s_addr = htonl(INADDR_ANY);
   else
   {
      hostAddress.sin_addr.s_addr = inet_addr((char *) hostName);
#if !defined(__VXWORKS__) // We don't support host name resolving with VxWorks
      if (hostAddress.sin_addr.s_addr == INADDR_NONE)
      {
         struct hostent *hostInfo;

         hostInfo = gethostbyname((char *) hostName);

         if (hostInfo == NULL)
            return (FTALK_TCPIP_CONNECT_ERR);
         hostAddress.sin_addr = *(struct in_addr *) hostInfo->h_addr;
      }
#endif
   }
   hostAddress.sin_port = htons(portNo);
   result = bind(listenSocket, (struct sockaddr *) &hostAddress,
                 sizeof (hostAddress));
   if (result == SOCKET_ERROR)
   {
      shutdownServer();
      switch (socketErrno)
      {
#ifdef _WINSOCKAPI_
         case WSAEACCES:
         return (FTALK_PORT_NO_ACCESS);
         case WSAEADDRINUSE:
         return (FTALK_PORT_ALREADY_BOUND);
         case WSAEADDRNOTAVAIL:
         default:
         return (FTALK_PORT_NOT_AVAIL);
#else
         case ENOTCONN: // Linux 7.2 reports this error no if no root privilege
         case EACCES:
         return (FTALK_PORT_NO_ACCESS);
         case EADDRINUSE:
         return (FTALK_PORT_ALREADY_BOUND);
         case EADDRNOTAVAIL:
         default:
         return (FTALK_PORT_NOT_AVAIL);
#endif
      }
   }

   //
   // Start listening to incoming connections
   //
   result = listen(listenSocket,
               ((MAX_CONNECTIONS < SOMAXCONN) ? MAX_CONNECTIONS : SOMAXCONN));
   if (result == SOCKET_ERROR)
   {
      shutdownServer();
      return (FTALK_LISTEN_FAILED);
   }
   return (FTALK_SUCCESS);
}

serverLoop()
{
   int iReturnCode = (FTALK_SUCCESS);
   int result;
   int sockIdx;
   int recvResult;
   int sendResult;
   fd_set fdSet;
   timeval timeVal;
   SOCKET maxFileDes;
   int replyCnt;
   int tcpOption;

   if (!isStarted())
      return (FTALK_ILLEGAL_STATE_ERROR);

   //
   // Prepare file descriptor set for select call
   //
   FD_ZERO (&fdSet);
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable: 4127)
#endif
   FD_SET (listenSocket, &fdSet);
#ifdef _MSC_VER
#  pragma warning(pop)
#endif
   maxFileDes = listenSocket;
   for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
   {
      if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable: 4127)
#endif
         FD_SET (connectionSocketArr[sockIdx], &fdSet);
#ifdef _MSC_VER
#  pragma warning(pop)
#endif
      if (connectionSocketArr[sockIdx] > maxFileDes)
         maxFileDes = connectionSocketArr[sockIdx];
   }

   //
   // Block until accept request or received data or time-out
   //
   timeVal.tv_sec = (long) timeOut / 1000L;
   timeVal.tv_usec = ((long) timeOut % 1000L) * 1000L;
   if (timeOut == 0)
      result = select((int) maxFileDes + 1, &fdSet, NULL, NULL, NULL);
   else
      result = select((int) maxFileDes + 1, &fdSet, NULL, NULL, &timeVal);
   if (result == SOCKET_ERROR)
      return (FTALK_FILEDES_EXCEEDED);

   //
   // Check for time-out
   //
   if (result == 0)
   {
      TRACELOG1("Slave poll time-out!\n");
      dataTablePtr->timeOutHandler();

      iReturnCode = (FTALK_REPLY_TIMEOUT_ERROR);
   }

   //
   // Connection accept request
   //
   if (FD_ISSET (listenSocket, &fdSet))
   {
      // Search a free socket
      for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
      {
         if (connectionSocketArr[sockIdx] == INVALID_SOCKET)
         {
            struct sockaddr_in peerAddr;
            SOCK_LEN_TYPE peerAddrLen = sizeof(peerAddr);

            // Yes, socket is free, try to accept a connection on it
            connectionSocketArr[sockIdx] = accept(listenSocket,
                                                  (struct sockaddr *) &peerAddr,
                                                  &peerAddrLen);
            if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
            {
               //
               // Check id connection shall be accepted
               //
               if (!dataTablePtr->validateMasterIpAddr(inet_ntoa(peerAddr.sin_addr)))
               {
                  shutdown(connectionSocketArr[sockIdx], SD_BOTH);
                  closesocket(connectionSocketArr[sockIdx]);
                  connectionSocketArr[sockIdx] = INVALID_SOCKET;
                  TRACELOG2("Connection rejected on slot %d\n", sockIdx);
               }

               //
               // Set socket options (we ignore errors here, not critical)
               //
#ifdef TCP_NODELAY
               tcpOption = 1; // Enable option
               setsockopt(connectionSocketArr[sockIdx],
                          IPPROTO_TCP, TCP_NODELAY,
                          (char *) &tcpOption, sizeof (tcpOption));
#endif
#ifdef SO_SNDBUF
               tcpOption = MAX_MSG_SIZE;
               setsockopt(connectionSocketArr[sockIdx],
                          SOL_SOCKET, SO_SNDBUF,
                          (char *) &tcpOption, sizeof (tcpOption));
#endif
#ifdef SO_RCVBUF
               tcpOption = MAX_MSG_SIZE;
               setsockopt(connectionSocketArr[sockIdx],
                          SOL_SOCKET, SO_RCVBUF,
                          (char *) &tcpOption, sizeof (tcpOption));
#endif
#ifdef SO_LINGER
               tcpOption = 0; // Disable option = discard unsent data when closing
               setsockopt(connectionSocketArr[sockIdx],
                          SOL_SOCKET, SO_LINGER,
                          (char *) &tcpOption, sizeof (tcpOption));
#endif
               TRACELOG2("Connection accepted on slot %d\n", sockIdx);
            }
            break; // Leave for loop
         }
      }
   }

   //
   // Data received on socket
   //

   for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
   {
      if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
      {
         if (FD_ISSET (connectionSocketArr[sockIdx], &fdSet))
         {
            recvResult = recv (connectionSocketArr[sockIdx],
                               (char *) bufferArr, sizeof (bufferArr), 0);
            sendResult = 0;
            replyCnt = 0;

            //
            // Process client message
            //
            if (recvResult >= PREFIX_LEN) // Process only minimum message sizes
            {
               short dataLen;

               dataLen = (short) ((bufferArr[4] << 8) | (bufferArr[5] & 0xFF));
               // Validate length before processing message
               if ((dataLen + PREFIX_LEN) == recvResult)
               {
                  replyCnt = processMessage(&bufferArr[PREFIX_LEN],
                                            recvResult - PREFIX_LEN);

                  // The first two bytes (msg id) are returned untouched
                  bufferArr[2] = 0; // protocol identifier
                  bufferArr[3] = 0; // protocol identifier
                  bufferArr[4] = (char) ((replyCnt) >> 8);
                  bufferArr[5] = (char) ((replyCnt) & 0xFF);
                  sendResult = send(connectionSocketArr[sockIdx],
                                    (char *) bufferArr,
                                    replyCnt + PREFIX_LEN, 0);
               }
            }
            //
            // Check for disconnection and errors
            //
            if ((recvResult < PREFIX_LEN) ||
                (sendResult != replyCnt + PREFIX_LEN))
            {
               //
               // Free socket
               //
               shutdown(connectionSocketArr[sockIdx], SD_BOTH);
               closesocket(connectionSocketArr[sockIdx]);
               connectionSocketArr[sockIdx] = INVALID_SOCKET;
               if (recvResult == 0)
                  TRACELOG2("Disconnected slot %d nicely by other peer.\n",
                            sockIdx);
               else
                  TRACELOG2("Forced disconnection on slot %d!\n", sockIdx);
            }
         }
      }
   }
   return iReturnCode;
}

Will the below code resolve my problem?

int ModbusTCPSlave::serverLoop()
{
   int iReturnCode = (FTALK_SUCCESS);
   int result;
   int sockIdx;
   int recvResult;
   int sendResult;
   fd_set fdSet;
   timeval timeVal;
   SOCKET maxFileDes;
   int replyCnt;
   int tcpOption;

   //if (!isStarted())
   //   return (FTALK_ILLEGAL_STATE_ERROR);

   //
   // Prepare file descriptor set for select call
   //
//   FD_ZERO (&fdSet);
//#ifdef _MSC_VER
//#  pragma warning(push)
//#  pragma warning(disable: 4127)
//#endif
//   FD_SET (listenSocket, &fdSet);
//#ifdef _MSC_VER
//#  pragma warning(pop)
//#endif
//   maxFileDes = listenSocket;
//   for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
//  {
//      if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
//#ifdef _MSC_VER
//#  pragma warning(push)
//#  pragma warning(disable: 4127)
//#endif
//         FD_SET (connectionSocketArr[sockIdx], &fdSet);
//#ifdef _MSC_VER
//#  pragma warning(pop)
//#endif
//      if (connectionSocketArr[sockIdx] > maxFileDes)
//         maxFileDes = connectionSocketArr[sockIdx];
//   }

   //
   // Block until accept request or received data or time-out
   //
   timeVal.tv_sec = (long) timeOut / 1000L;
   timeVal.tv_usec = ((long) timeOut % 1000L) * 1000L;
   if (timeOut == 0)
      result = select((int) maxFileDes + 1, &fdSet, NULL, NULL, NULL);
   else
      result = select((int) maxFileDes + 1, &fdSet, NULL, NULL, &timeVal);
//   if (result == SOCKET_ERROR)
//      return (FTALK_FILEDES_EXCEEDED);

   //
   // Check for time-out
   //
//   if (result == 0)
//   {
//      TRACELOG1("Slave poll time-out!\n");
//      dataTablePtr->timeOutHandler();
//
//    iReturnCode = (FTALK_REPLY_TIMEOUT_ERROR);
//   }

   //
   // Connection accept request
   //
 //  if (FD_ISSET (listenSocket, &fdSet))
   {
      // Search a free socket
 //     for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
      {
  //       if (connectionSocketArr[sockIdx] == INVALID_SOCKET)
         {
            struct sockaddr_in peerAddr;
            SOCK_LEN_TYPE peerAddrLen = sizeof(peerAddr);

            // Yes, socket is free, try to accept a connection on it
            connectionSocketArr[sockIdx] = accept(listenSocket,
                                                  (struct sockaddr *) &peerAddr,
                                                  &peerAddrLen);
//           if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
//           {
//               //
//               // Check id connection shall be accepted
//               //
//               if (!dataTablePtr->validateMasterIpAddr(inet_ntoa(peerAddr.sin_addr)))
//               {
//                  shutdown(connectionSocketArr[sockIdx], SD_BOTH);
//                  closesocket(connectionSocketArr[sockIdx]);
//                  connectionSocketArr[sockIdx] = INVALID_SOCKET;
//                  TRACELOG2("Connection rejected on slot %d\n", sockIdx);
//               }

               //
               // Set socket options (we ignore errors here, not critical)
               //
//#ifdef TCP_NODELAY
//               tcpOption = 1; // Enable option
//               setsockopt(connectionSocketArr[sockIdx],
//                          IPPROTO_TCP, TCP_NODELAY,
//                          (char *) &tcpOption, sizeof (tcpOption));
//#endif
//#ifdef SO_SNDBUF
//               tcpOption = MAX_MSG_SIZE;
//               setsockopt(connectionSocketArr[sockIdx],
//                          SOL_SOCKET, SO_SNDBUF,
//                          (char *) &tcpOption, sizeof (tcpOption));
//#endif
//#ifdef SO_RCVBUF
//               tcpOption = MAX_MSG_SIZE;
//               setsockopt(connectionSocketArr[sockIdx],
//                          SOL_SOCKET, SO_RCVBUF,
//                          (char *) &tcpOption, sizeof (tcpOption));
//#endif
//#ifdef SO_LINGER
//               tcpOption = 0; // Disable option = discard unsent data when closing
//               setsockopt(connectionSocketArr[sockIdx],
//                          SOL_SOCKET, SO_LINGER,
//                          (char *) &tcpOption, sizeof (tcpOption));
//#endif
//               TRACELOG2("Connection accepted on slot %d\n", sockIdx);
//            }
//           break; // Leave for loop
//         }
//      }
//   }

   //
   // Data received on socket
   //

//   for (sockIdx = 0; sockIdx < MAX_CONNECTIONS; sockIdx++)
//   {
//      if (connectionSocketArr[sockIdx] != INVALID_SOCKET)
//    {
//         if (FD_ISSET (connectionSocketArr[sockIdx], &fdSet))
//         {
            recvResult = recv (connectionSocketArr[sockIdx],
                               (char *) bufferArr, sizeof (bufferArr), 0);
            sendResult = 0;
            replyCnt = 0;

            //
            // Process client message
            //
            if (recvResult >= PREFIX_LEN) // Process only minimum message sizes
            {
               short dataLen;

               dataLen = (short) ((bufferArr[4] << 8) | (bufferArr[5] & 0xFF));
               // Validate length before processing message
               if ((dataLen + PREFIX_LEN) == recvResult)
               {
                  replyCnt = processMessage(&bufferArr[PREFIX_LEN],
                                            recvResult - PREFIX_LEN);

                  // The first two bytes (msg id) are returned untouched
                  bufferArr[2] = 0; // protocol identifier
                  bufferArr[3] = 0; // protocol identifier
                  bufferArr[4] = (char) ((replyCnt) >> 8);
                  bufferArr[5] = (char) ((replyCnt) & 0xFF);
                  sendResult = send(connectionSocketArr[sockIdx],
                                    (char *) bufferArr,
                                    replyCnt + PREFIX_LEN, 0);
               }
            }
            //
            // Check for disconnection and errors
            //
            if ((recvResult < PREFIX_LEN) ||
                (sendResult != replyCnt + PREFIX_LEN))
            {
               //
               // Free socket
               //
               shutdown(connectionSocketArr[sockIdx], SD_BOTH);
               closesocket(connectionSocketArr[sockIdx]);
               connectionSocketArr[sockIdx] = INVALID_SOCKET;
               if (recvResult == 0)
                  TRACELOG2("Disconnected slot %d nicely by other peer.\n",
                            sockIdx);
               else
                  TRACELOG2("Forced disconnection on slot %d!\n", sockIdx);
            }
//         }
//    }
//   }
   return iReturnCode;
}

Thanks Valter, You are right, I got it. I've one more query in code there are two arrays regdata[30][65535]; and bitarray[30][2000] after reading data from a file I can decide the first dimension of array i.e. [30]..if data in file is for two slave id then i require regdata[2][65535] and bitarray[2][2000]..how I can manage this assignment at runtime? I tried using vector like struct{ regdata[65535]; bitarray[2000]; }regstack; after reading file I tried to push_back() regstack, but it gives heap error..how I can resize this array in runtime?

도움이 되었습니까?

해결책

You can't have multiple sockets listening on the same port. But if the address is validated inside processMessage couln't you simply change that function to accept requests for different slave IDs.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top