02-07-2014 01:39 PM
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?
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; }