📄 mbserver.cpp
字号:
// 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 + -