123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- #include "stdafx.h"
- #include ".\clientsocket.h"
- #include <comdef.h>
- #include <atlbase.h>
- #include "modbustcp.h"
- //#include "Client2SrvType.h"
- #pragma warning(push)
- #pragma warning(disable:4995)
- #pragma warning(pop)
- const int AF_IPV4 = 0;
- const int AF_IPV6 = 1;
- const int SOCK_TCP = SOCK_STREAM-1;
- const int SOCK_UDP = SOCK_DGRAM-1;
- CClientSocket::CClientSocket(void)
- {
- m_nMode = AF_IPV4;
- m_nSockType = SOCK_TCP;
- m_SocketClient.SetInterface(this);
- m_bSocket = FALSE;
- #if IS_USE_EVENT
- MTVERIFY( m_hSemNet = CreateEvent( NULL, TRUE, TRUE, 0 ) );
- #endif
- MTVERIFY (m_hRunObject = ::CreateEvent(
- NULL, /* Security */
- TRUE, /* Manual event */
- 0, /* Clear on creation */
- "modbusTcp::m_hRunObject"));
- //InitializeCriticalSection( &m_csWrFinished );
- }
- CClientSocket::~CClientSocket(void)
- {
- if( m_hRunObject != NULL )
- {
- MTVERIFY( CloseHandle( m_hRunObject ) );
- m_hRunObject = NULL;
- }
- #if IS_USE_EVENT
- if( m_hSemNet != NULL )
- {
- MTVERIFY( CloseHandle( m_hSemNet ));
- m_hSemNet = NULL;
- }
- #endif
- //DeleteCriticalSection( &m_csWrFinished );
- }
- bool CClientSocket::GetDestination(SockAddrIn& addrIn) const
- {
- CString strIPAddress, strPort;
- int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
- return addrIn.CreateFrom(strIPAddress, strPort, nFamily);
- }
- int CClientSocket::ClientSend(char* pMsg, int iLen)
- {
- if ( m_SocketClient.IsOpen() )
- {
- if ( pMsg == NULL ) {
- return -1;
- }
- USES_CONVERSION;
- if (m_nSockType == SOCK_TCP)
- {
- return m_SocketClient.Write((const LPBYTE)(pMsg), iLen, NULL);
- }
- else
- {
- SockAddrIn sockAddr;
- GetDestination(sockAddr);
- m_SocketClient.Write((const LPBYTE)(pMsg), iLen, sockAddr);
- }
- }
- else
- {
- ;//MessageBox(_T("Socket is not connected"));
- }
- return 0;
- }
- BOOL CClientSocket::Connection(LPCTSTR strAddr, LPCTSTR strPort)
- {
- int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
- if ( !m_SocketClient.StartClient(NULL, strAddr, strPort, nFamily, (m_nSockType+1) ) )
- {
- //MessageBox(NULL, _T("连接服务器失败!"), "提示", MB_ICONSTOP);
- return FALSE;
- }
- else
- {
- CSocketHandle* pSH = (CSocketHandle *)m_SocketClient;
- pSH->m_nPendingSize = 0;
- memset(pSH->m_PendingBuffer, 0, SOCKET_BUFFSIZE);
- SetupMCAST();
- return TRUE;
- }
- }
- void CClientSocket::DisConnection()
- {
- m_SocketClient.Terminate();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // 实现ISocketClientHandler的通信方法
- void CClientSocket::OnThreadBegin(CSocketHandle* pSH)
- {
- ASSERT( pSH == m_SocketClient );
- (pSH);
- CString strAddr;
- SockAddrIn sockAddr;
- m_SocketClient->GetSockName(sockAddr);
- GetAddress( sockAddr, strAddr );
- InitializeCriticalSection(&pSH->m_hClient2SrvSection);
- //AppendText( _T("Client Running on: %s\r\n"), strAddr);
- }
- void CClientSocket::OnThreadExit(CSocketHandle* pSH)
- {
- ASSERT( pSH == m_SocketClient );
- DeleteCriticalSection( &pSH->m_hClient2SrvSection );
- (pSH);
- }
- void CClientSocket::OnDataReceived(CSocketHandle* pSH, const BYTE* pbData, DWORD dwCount, const SockAddrIn& addr)
- {
- ASSERT( pSH == m_SocketClient );
- (pSH);
- if( !m_SocketClient->IsOpen() ) return;
-
- //ProcessData( pSH, pbData, dwCount );
- int nRet;
- nRet = OnCmdProcess( (void *)pbData, dwCount);
- if( nRet == -1 )
- {
- TRACE("crc32 error \r\n");
- }
- }
- void CClientSocket::OnConnectionDropped(CSocketHandle* pSH)
- {
- ASSERT( pSH == m_SocketClient );
- (pSH);
- TRACE(_T("======连接服务器断开.\r\n"));
-
- m_bSocket = FALSE;
- }
- void CClientSocket::OnConnectionError(CSocketHandle* pSH, DWORD dwError)
- {
- ASSERT( pSH == m_SocketClient );
- (pSH);
- _com_error err(dwError);
- m_bSocket = FALSE;
- }
- bool CClientSocket::SetupMCAST()
- {
- const TCHAR szIPv4MCAST[] = TEXT("239.121.1.2");
- const TCHAR szIPv6MCAST[] = TEXT("FF02:0:0:0:0:0:0:1"); // All Nodes local address
- bool result = false;
- if ( m_nSockType == SOCK_UDP )
- {
- if ( m_nMode == AF_IPV4 ) {
- result = m_SocketClient->AddMembership(szIPv4MCAST, NULL);
- } else {
- result = m_SocketClient->AddMembership(szIPv6MCAST, NULL);
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
- hr = hr;
- }
- }
- return result;
- }
- void CClientSocket::GetAddress(const SockAddrIn& addrIn, CString& rString) const
- {
- TCHAR szIPAddr[MAX_PATH] = { 0 };
- CSocketHandle::FormatIP(szIPAddr, MAX_PATH, addrIn);
- rString.Format(_T("%s : %d"), szIPAddr, static_cast<int>(static_cast<UINT>(ntohs(addrIn.GetPort()))) );
- }
- void CClientSocket::ProcessData(CSocketHandle *pSH, const BYTE* pData, DWORD nLen)
- {
- DWORD nBuffIndex = 0;
- EnterCriticalSection( &(pSH->m_hClient2SrvSection) );
- while( nBuffIndex < nLen )
- {
- //ProtocolHeader *pHeader; //当前协议包头
- HEADER *pHeader;
- int iAllLen = 0;
- DWORD nProcessedLen = 0; //当前循环处理了多少个字节
- if( pSH->m_nPendingSize > 0 ) // 开始组包
- {
- pHeader = (HEADER *)pSH->m_PendingBuffer;
- iAllLen = htons(pHeader->ByteNum) + 6;
- if( pSH->m_nPendingSize < sizeof(HEADER) ) //上一次接收到的长度小于包头
- {
- DWORD nLinkHeaderLen = sizeof( HEADER ) - pSH->m_nPendingSize;
- if( nLinkHeaderLen <= nLen ) //这次可以收完包头
- {
- memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLinkHeaderLen );//这里已经收完Header
- nProcessedLen = iAllLen - pSH->m_nPendingSize;
- if( nProcessedLen <= nLen ) //如果所需处理的长度小于等于当前包长度
- {
- memcpy( &pSH->m_PendingBuffer[ sizeof( HEADER ) ],
- & ( ( char *) pData )[ nLinkHeaderLen ],
- iAllLen - sizeof( HEADER ) );
- pSH->m_nPendingSize = 0; // 收完所需的包,置m_nPendingSize为0
- }
- else
- {
- int nTemp = nLen - nLinkHeaderLen; //除去头剩余部分的长度
- if ( nTemp > 0 ) //刚好是Header的长度,不用拷贝内存,所以这里加了>0的判断
- {
- memcpy( &pSH->m_PendingBuffer[ sizeof( HEADER ) ],
- & ( ( char *) pData )[ nLinkHeaderLen ],
- nTemp );
- }
- pSH->m_nPendingSize += nLen;
- }
- }
- else //这次还是没有收完包头, 继续Pending
- {
- memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLen );
- pSH->m_nPendingSize += nLen;
- nProcessedLen = nLen;
- }
- }
- else //Header部分已经在阻塞的缓冲区中
- {
- nProcessedLen = iAllLen - pSH->m_nPendingSize;
- if ( nProcessedLen <= nLen ) //如果需要处理的长度小于现有包的长度
- {
- memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nProcessedLen );
- pSH->m_nPendingSize = 0;
- }
- else //否则要继续阻塞
- {
- memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLen );
- pSH->m_nPendingSize += nLen;
- }
- }
- }
- else //第一次接包
- {
- pHeader = (HEADER *)&( (unsigned char *)pData )[nBuffIndex];
- iAllLen = htons(pHeader->ByteNum) + 6;
- if( nLen - nBuffIndex < sizeof(HEADER) ) // 没有收够包头,先记录当前收到的Buffer
- {
- //如果第一次接包就没有收够包头,认为是非法包,扔掉,就是说已处理的长度nProcessedLen = 0
- pSH->m_nPendingSize = nLen - nBuffIndex;
- memcpy(pSH->m_PendingBuffer, pHeader, pSH->m_nPendingSize);
- }
- else
- {
- nProcessedLen = iAllLen;
- if( iAllLen > (int)(nLen - nBuffIndex) )
- {
- memcpy(pSH->m_PendingBuffer, pHeader, nLen - nBuffIndex);
- //如果第一次接包,pHeader->nLen大于当前包的总长,认为是非法包,扔掉
- if( 0 == nBuffIndex )
- {
- //组包错误,则扔掉当前包
- TRACE("iAllLen大于当前包的总长,认为是非法包,扔掉\r\n");
- break;
- }
- pSH->m_nPendingSize = nLen - nBuffIndex;
- nProcessedLen = nLen - nBuffIndex;
- }
- else
- {
- pSH->m_nPendingSize = 0;
- }
- }
- }
- if ( nProcessedLen == 0 )
- {
- // 没有收够包头,认为是非法包,扔掉
- TRACE("没有收够包头,认为是非法包,扔掉\r\n");
- break;
- }
- if ( pSH->m_nPendingSize == 0 )
- {
- if ( iAllLen > SOCKET_BUFFSIZE )
- {
- // 包长度超过限制
- TRACE("pHeader->nLen超过限制\r\n");
- }
- if(-1 == OnCmdProcess( pHeader, nLen))
- {
- //MessageBox( NULL, "Error OnCmdProcess", NULL, MB_OK );
- TRACE("crc校验错误!\r\n");
- break;
- }
- }
- nBuffIndex += nProcessedLen;
- }
- LeaveCriticalSection( &(pSH->m_hClient2SrvSection) );
- }
- int CClientSocket::OnCmdProcess(void *pData, int iDataLen)
- {
- HEADER TmpHeader = {0};
- char *pTmpData = new char[iDataLen];
- memcpy(pTmpData, pData, iDataLen);
- memcpy(&TmpHeader, pTmpData, sizeof(HEADER));
- switch(TmpHeader.FuncCode)
- {
- case 0x03://读数据应答
- ReadDataRes(pTmpData);
- break;
- case 0x10://写数据应答
- WriteDataRes(pTmpData);
- break;
-
- case (0x03 + 0x80)://读数据应答异常
- ReadDataResError(pTmpData);
- break;
- case 0x90://写数据应答异常
- WriteDataResError(pTmpData);
- break;
- default://错误的功能包
- if( pTmpData )
- {
- delete[] pTmpData;
- pTmpData = NULL;
- }
- return -1;
- }
- if( pTmpData )
- {
- delete[] pTmpData;
- pTmpData = NULL;
- }
- return 0;
- }
- int CClientSocket::ReadDataRes(char *pTmpData)
- {
- RESPONSE_STRUCT ResponseStr = {0};
- int iHeadLen = sizeof(ResponseStr.Header);
- memcpy(&ResponseStr.Header, pTmpData, iHeadLen);
- memcpy(&ResponseStr.DataLen, pTmpData + iHeadLen, sizeof(ResponseStr.DataLen));
- if (ResponseStr.DataLen > 0)
- {
- memcpy(&ResponseStr.StrRtnMsg, pTmpData + iHeadLen + 1, ResponseStr.DataLen);
- ResponseStr.nReadResult = 1;
- m_structResponse = ResponseStr;
- //TRACE("DataLen1 = %d\r\n", m_structResponse.DataLen);
- }
- else
- {
- ResponseStr.nReadResult = 0;
- m_structResponse = ResponseStr;
- //TRACE("返回数据长度=%d\r\n", ResponseStr.DataLen);
- return -1;
- }
- int nValue;
- WORD wdValue;
- memcpy(&wdValue, ResponseStr.StrRtnMsg, sizeof(WORD));
- //wdValue = htons(wdValue);
- nValue = htons(wdValue);
- //TRACE(">>>>>>>>>结束请求,数据内容=%d\r\n", nValue);
- #if IS_USE_EVENT
- SetEvent( m_hSemNet );
- #endif
- return 0;
- }
- int CClientSocket::WriteDataRes(char *pTmpData)
- {
- memcpy(&m_structWriteResponse, pTmpData, sizeof(WRITESUCCESSRESPONSE));
- #if IS_USE_EVENT
- SetEvent( m_hSemNet );
- #endif
- return 0;
- }
- int CClientSocket::ReadDataResError(char *pTmpData)
- {
- FAILRESPONSE ResponseStr;
- memcpy(&ResponseStr, pTmpData, sizeof(FAILRESPONSE));
- TRACE("读数据错误\r\n");
- return 0;
- }
- int CClientSocket::WriteDataResError(char *pTmpData)
- {
- return 0;
- }
- int CClientSocket::WorkMain(REQUESTPARAM SetBasePara)
- {
- if(!m_SocketClient)
- {
- TRACE("打开端口错误\r\n");
- return ERR_CODE_MODBUS_TCP_NET_FAULT; // 端口通信故障
- }
- int nRet;
- nRet = RequestStatus(&SetBasePara, sizeof(REQUESTPARAM));
- if( nRet != 0 )
- {
- return nRet; // 端口忙
- }
- return nRet;
- }
- int CClientSocket::Write(REQUESTWRPARAM writeParam)
- {
- if(!m_SocketClient)
- {
- TRACE("打开端口错误\r\n");
- return ERR_CODE_MODBUS_TCP_NET_FAULT; // 端口通信故障
- }
- int nRet;
- nRet = RequestStatus(&writeParam, sizeof(REQUESTWRPARAM) - sizeof(writeParam.nWriteResult));
- if( nRet != 0 )
- {
- return nRet; // 端口忙
- }
- return nRet;
- }
- int CClientSocket::RequestStatus(void *pData, int nLen)
- {
- //int iLen = sizeof(REQUESTPARAM);
- //TRACE("开始请求一个变量数据\r\n");
- //TRACE("开始请求寄存器起始地址=%d\r\n", htons(SetBasePara.StartAddr));
- #if IS_USE_EVENT
- if( WaitForSingleObject( m_hSemNet, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口
- {
- ResetEvent( m_hSemNet );
- #endif
- int nResult = ClientSend((char *)pData, nLen);
-
- if( nResult == nLen )
- {
- ;
- }
- else
- {
- #if IS_USE_EVENT
- SetEvent( m_hSemNet );
- #endif
- TRACE("发送数据错误\r\n");
- return EER_CODE_MODBUS_TCP_NET_WRITE_DATA;
- }
- #if IS_USE_EVENT
- }
- else
- {
- return ERR_CODE_MODBUS_TCP_NET_BUSY;
- }
- #endif
- return 0;
- }
- DWORD WINAPI CClientSocket::ReConnectSrvThread( void *pData )
- {
- CClientSocket *pClientSocket = (CClientSocket *)pData;
- do
- {
- if( pClientSocket->m_bSocket == FALSE )
- {
- if ( pClientSocket->m_SocketClient.IsOpen() )
- {
- pClientSocket->DisConnection();
- }
- char chNetPort[8] = {0};
- itoa(pClientSocket->m_nNetPort, chNetPort, 10);
- if( !pClientSocket->Connection(pClientSocket->m_chIpAddr, chNetPort) )
- {
- pClientSocket->m_bSocket = FALSE;
- }
- else
- {
- pClientSocket->m_bSocket = TRUE;
- }
- }
- }while( WaitForSingleObject( pClientSocket->m_hRunObject, 125L ) == WAIT_TIMEOUT );
- return 0;
- }
|