我正在使用win ce 6 modbus tcp客戶端服務器,應用程序是爲客戶端服務器通信而開發的,並且工作正常。現在req是我的從屬設備應該響應由主/客戶端輪詢的差分從地址。我可以只更改從屬身份和建立連接,或者我需要關閉以前的連接,並再次建立新的連接modbus tcp clent服務器與多個從服務器ID
下面是代碼,這是工作正常的一個節點,如果我與其他節點ID輪詢,然後它會給出例外。它需要什麼改變才能同時與其他節點通信。我的設備應該能夠與modbus tcp上的32個diff節點進行通信。我應該爲每個節點創建單獨的線程,但它們將如何在同一端口上進行通信?在與其他節點建立連接之前,我應關閉前一個節點嗎?
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;
}
下面的代碼能解決我的問題嗎?
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 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;
}
謝謝Valter,你說得對,我明白了。我在代碼中有一個查詢有兩個數組regdata [30] [65535];和bitarray [30] [2000]從文件中讀取數據後,我可以決定數組的第一維,即[30] ..如果文件中的數據是用於兩個從機ID,那麼我需要regdata [2] [65535]和bitarray [ 2] [2000] ..我如何在運行時管理這個任務?我試圖使用向量像struct{ regdata[65535]; bitarray[2000]; }regstack; after reading file I
試圖push_back()regstack,但它給堆錯誤..我可以在運行時調整這個數組?
我可以coomunicate在相同的端口和IP地址的diff節點? – user1586695
可以任何幫助我 – user1586695
Modbus TCP專家請hepl – user1586695