⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbserver.cpp

📁 MODBUS TCP(C++)Example ModbusTCP server - source and WIN32 executable有可执行文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // set socket non-blocking in case a client has second thoughts about
    // establishing a connection later on. In this case the accept() will return
    // with an error rather than with a socket.

    if (ioctlsocket (s, FIONBIO, &nbiotrue)) 
    {
        printf("ioctlsocket - error %d\n", WSAGetLastError());
    }

    i = listen(s, numSockets);
    if (i<0)
    {
        printf("listen - error %d\n",WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }

    // at this point, be prepared to handle incoming requests on socket s
    // by doing accept() and processing them independently

    for (;;) 
    {

        SOCKET cs;
        fd_set fds;
        int si;
        struct timeval tv;

        // set up a 1 second timeout to allow for (future) background activity

        tv.tv_sec = 1;
        tv.tv_usec = 0;

        // be prepared for incoming messages on the listen port and any active ports

        FD_ZERO(&fds);

        // wait for incoming connection
        FD_SET(s, &fds);

        // and add any Modbus sessions
        for (i=0;i<numSockets;i++) 
        {
            if (csa[i] != INVALID_SOCKET) 
            {
                cs = csa[i];
                FD_SET(cs, &fds);
            }
        }

        i = select(32, &fds, NULL, NULL, &tv); // read

        // note that the fd_set will have been updated to select only those sockets 
        // requiring attention right now

        if (i<0)
        {
            printf("select - error %d\n",WSAGetLastError());
            closesocket(s);
            WSACleanup();
            return 1;
        }

        // any listen work?

        if (FD_ISSET(s, &fds)) 
        {
            printf("new connection received\n");
            cs = accept(s,NULL,0);
            if (cs<0)
            {
                int e = WSAGetLastError();
                if (e != WSAEWOULDBLOCK) 
                {
                    printf("accept - error %d\n",e);
                    closesocket(s);
                    WSACleanup();
                    return 1;
                } else 
                {
                    // the connection is no longer pending so it must have been
                    // abandoned by the client
                }
            } else 
            {

                // add the newly opened socket to the list. If nowhere to put it, throw it 
                // away

                for (i=0;i<numSockets;i++) 
                {
                    if (csa[i] == INVALID_SOCKET) 
                    {
                        csa[i] = cs;
                        frag[i].fragLen = 0;
						openTime[i] = time(NULL);
                        break;
                    }
                }

                if (i >= numSockets) 
                {
                    // nowhere to put it
                    printf("connection abandoned - maximum concurrent sessions reached\n");
                    closesocket(cs);
                }

                // set socket non-blocking just in case anything happens which might make the 
                // recv() operation block later on. This should not be necessary.

                if (ioctlsocket (cs, FIONBIO, &nbiotrue)) 
                {
                    printf("ioctlsocket - error %d\n", WSAGetLastError());
                }

            }
        }

        // any socket level work?

        for (si=0;si<numSockets;si++) 
        {
            struct fragMsg *thisFrag;
            unsigned char *ibuf;

            cs = csa[si];

            if (cs == INVALID_SOCKET) 
            {
                // nothing to do right now on this one
                continue;
            }

#if IDLE_TIMEOUT
			if (10 <= difftime(time(NULL), openTime[si])) 
			{
				// the 10 second idle timer has expired. Close the incoming session
				printf("closing session %d because idle time expired\n");
                // remove session from active list
                csa[si] = INVALID_SOCKET;
                // close connection
                closesocket(cs);
                continue; // abandon any further processing on this session
			}
#endif // IDLE_TIMEOUT

            if (!FD_ISSET(cs, &fds)) 
            {
                // nothing to do right now on this one
                continue;
            }

#if IDLE_TIMEOUT
			// ags 1/18/01
			// update timeout so that shhutdown only occurs after 10 sec of IDLE
			// and not arbitrarily 10 sec from session open!
			openTime[si] = time(NULL);
#endif // IDLE_TIMEOUT

            cs = csa[si];

            // account for any fragment outstanding from a previous cycle
            // (this stupidity would not be necessary if all clients would send
            // their messages in one piece)

            thisFrag = &frag[si];
            ibuf = thisFrag->fragBuf;

            if (thisFrag->fragLen < 6) 
            {
                // don't know the length yet, just read the prefix
                i = recv(cs, (char *)&thisFrag->fragBuf[thisFrag->fragLen], 6 - thisFrag->fragLen, 0);
                if (i <= 0) 
                {
                    // this session has been closed or damaged at the remote end
                    // this may be a normal condition

                    // remove session from active list
                    csa[si] = INVALID_SOCKET;
                    // close connection
                    closesocket(cs);
                    continue;
                }
                thisFrag->fragLen += i;

                // unfortunately, we are not sure if there are any more bytes
                // so continue this processing on the next cycle
                continue;
            }

            if (ibuf[2] != 0 || ibuf[3] != 0 || ibuf[4] != 0 || ibuf[5] < 2) 
            {
                // this is not legitimate Modbus/TCP
                // possibly your client is very confused
                // close down the connection

                // remove session from active list
                csa[si] = INVALID_SOCKET;
                printf("bad MB/TCP protocol - closing\n");
                // close connection
                closesocket(cs);
                continue;
            }

            // the real length is in ibuf[5]

            if (thisFrag->fragLen < 6+ibuf[5]) 
            {
                i = recv(cs, (char *)&thisFrag->fragBuf[thisFrag->fragLen], 6 + ibuf[5] - thisFrag->fragLen, 0);
                if (i <= 0) 
                {
                    // this session has been closed or damaged at the remote end
                    printf("session closed with partial request outstanding\n", i);
                    // remove session from active list
                    csa[si] = INVALID_SOCKET;
                    // close connection
                    closesocket(cs);
                    continue;
                }
                thisFrag->fragLen += i;
            }
            if (thisFrag->fragLen < 6+ibuf[5]) 
            {
                // still waiting for completion of the message
                continue;
            }

            // if we get here, the message is complete and it looks like MB/TCP

            // process the incoming request, generating a response
            // note that there is no requirement to keep track of which connection
            // the request was received on - you must only use the same one for 
            // sending the response

            i = processMsg(ibuf, thisFrag->fragLen);

            i = send(cs, (char *)ibuf, i, 0);

            thisFrag->fragLen = 0;

        }
        // note that this outer loop will run forever unless cancelled
        // and that if it is cancelled, you must close outstanding sockets
        // and call WSACleanup()
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -