CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Modbus TCP multiple node communication*** Locked - off topic

 
Post new topic   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
asd



Joined: 06 Feb 2014
Posts: 1

View user's profile Send private message

Modbus TCP multiple node communication*** Locked - off topic
PostPosted: Thu Feb 06, 2014 8:15 pm     Reply with quote

++++++++++++++++++++
Locked.

Reason: Visual C++ is off-topic on CCS C compiler for Microchip PIC
microcontrollers forum.

- Forum Moderator
++++++++++++++++++++


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 requirement is my slave device should respond to the different 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 is required to communicate with other node simultaneously ? My device should be able to communicate with 32 different nodes on modbus tcp. Shall I create individual threads for each node ? But how will they communicate on same port? Before establishing connection with other node shall I close previous node?
Code:

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;
}

Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group