c++ - modbus tcp clent server with multiple slave id -
i'm working on win ce 6 modbus tcp client server, application developed client server communication , working fine. req slave device should respond diff slave addresses polled master/client. can change slave id , establish connection or need close previous connection , again establish new one
below code, working fine 1 node, if polled other node id gives exception. change req communicate other node simultaneously. device should able communicate 32 diff nodes on modbus tcp. shall create individual threads each node how communicate on same port? before establishing connection other node shall 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: tcp allow 0 slave address, -1 means ignore slave adr if ((slaveaddr < -1) || (slaveaddr > 255)) return (ftalk_illegal_argument_error); this->slaveaddr = slaveaddr; // // special treatment win32 platform, needs 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 listen socket 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__) // don't support host name resolving 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 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 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 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; (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 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 free socket (sockidx = 0; sockidx < max_connections; sockidx++) { if (connectionsocketarr[sockidx] == invalid_socket) { struct sockaddr_in peeraddr; sock_len_type peeraddrlen = sizeof(peeraddr); // yes, socket free, try accept connection on connectionsocketarr[sockidx] = accept(listensocket, (struct sockaddr *) &peeraddr, &peeraddrlen); if (connectionsocketarr[sockidx] != invalid_socket) { // // check id connection shall 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 loop } } } // // data received on socket // (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 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); // first 2 bytes (msg id) 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 disconnection , 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 other peer.\n", sockidx); else tracelog2("forced disconnection on slot %d!\n", sockidx); } } } } return ireturncode; }
will below code resolve 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 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; // (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 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 free socket // (sockidx = 0; sockidx < max_connections; sockidx++) { // if (connectionsocketarr[sockidx] == invalid_socket) { struct sockaddr_in peeraddr; sock_len_type peeraddrlen = sizeof(peeraddr); // yes, socket free, try accept connection on connectionsocketarr[sockidx] = accept(listensocket, (struct sockaddr *) &peeraddr, &peeraddrlen); // if (connectionsocketarr[sockidx] != invalid_socket) // { // // // // check id connection shall 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 loop // } // } // } // // data received on socket // // (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 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); // first 2 bytes (msg id) 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 disconnection , 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 other peer.\n", sockidx); else tracelog2("forced disconnection on slot %d!\n", sockidx); } // } // } // } return ireturncode; }
thanks valter, right, got it. i've 1 more query in code there 2 arrays regdata[30][65535]; , bitarray[30][2000] after reading data file can decide first dimension of array i.e. [30]..if data in file 2 slave id require regdata[2][65535] , bitarray[2][2000]..how can manage assignment @ runtime? tried using vector struct{ regdata[65535]; bitarray[2000]; }regstack; after reading file i
tried push_back() regstack, gives heap error..how can resize array in runtime?
you can't have multiple sockets listening on same port. if address validated inside processmessage couln't change function accept requests different slave ids.
Comments
Post a Comment