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

📄 comm_mon.cpp

📁 比较详尽的介绍了短信的发送与接收的实现模块与程序
💻 CPP
字号:

// comm_mon.cpp


#include "stdafx.h"
#include "comm_mon.h"
#include "commspy.h"






GCommMonitor::GCommMonitor()
{
   m_hConn = NULL;
   m_hMPP = NULL;

   m_pConn = NULL;
   m_pMPP = NULL;
}


GCommMonitor::~GCommMonitor()
{
   if(m_pConn && m_pConn->bConnected)
   {
      TRACE(_T("Warning: terminating COMM connection in GCommMonitor::~GCommMonitor()\n"));
      Disconnect();
   }

   if(m_hConn)
   {
      ::GlobalUnlock(m_hConn);
      ::GlobalFree(m_hConn);
   }

   if(m_hMPP)
   {
      ::GlobalUnlock(m_hMPP);
      ::GlobalFree(m_hMPP);
   }
}


BOOL GCommMonitor::IsConnected() const
{
   return (m_pConn && m_pConn->bConnected);
}



BOOL GCommMonitor::Connect(LPTTYSTRUCT lpTTY)
{
   if(m_pConn && m_pConn->bConnected)
      return TRUE;

   // only allocate this guy once
   if(!m_hConn)
   {
      m_hConn = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(CONNECTION));
      m_pConn = (LPCONNECTION)::GlobalLock(m_hConn);
      ZeroMemory(m_pConn, sizeof(CONNECTION));
   }

   // create I/O event used for overlapped reads/writes
   if((m_pConn->osRead.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
      return FALSE;

   if((m_pConn->osWrite.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
      return FALSE;
   
   // open communcations file
   CString strPort;
   if(lpTTY->byCommPort > 3)
   {
      strPort = "\\\\.\\TELNET";
   }
   else
   {
      strPort.Format(_T("COM%d"), lpTTY->byCommPort + 1);
   }

   m_pConn->hCommDev = ::CreateFile(strPort, GENERIC_READ|GENERIC_WRITE, 0,
                                  NULL, OPEN_EXISTING, 
                                  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 
                                  NULL);

   if(m_pConn->hCommDev == INVALID_HANDLE_VALUE)
      return FALSE;
   
   BOOL bPurge = FALSE;
   // get any early notifications
   if(::SetCommMask(m_pConn->hCommDev, EV_RXCHAR))
   {
      // setup device buffers
      if(::SetupComm(m_pConn->hCommDev, 4096, 4096))
      {
         // purge any information in the buffer
         if(::PurgeComm(m_pConn->hCommDev, PURGE_TXABORT|PURGE_RXABORT|
                                           PURGE_TXCLEAR|PURGE_RXCLEAR))
         {
            bPurge = TRUE;
         }
      }
   }
   
   if(!bPurge)
   {
      ::CloseHandle(m_pConn->hCommDev);
      return FALSE;
   }

   // set up for overlapped I/O
   COMMTIMEOUTS CommTimeOuts;

   CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
   CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
   CommTimeOuts.ReadTotalTimeoutConstant = 1000;
   CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
   CommTimeOuts.WriteTotalTimeoutConstant = 1000;

   if(!::SetCommTimeouts(m_pConn->hCommDev, &CommTimeOuts))
   {
      ::CloseHandle(m_pConn->hCommDev);
      return FALSE;
   }

   // set up the connect
   DCB dcb;
   ZERO_MEMORY(dcb);
   dcb.DCBlength = sizeof(DCB);

   if(!::GetCommState(m_pConn->hCommDev, &dcb))
   {
      ::CloseHandle(m_pConn->hCommDev);
      return FALSE;
   }

   dcb.BaudRate = lpTTY->dwBaudRate;
   dcb.ByteSize = lpTTY->byByteSize;
   dcb.Parity = lpTTY->byParity;
   dcb.StopBits = lpTTY->byStopBits;

   // setup hardware flow control
   BOOL bSet = (BYTE)((lpTTY->byFlowCtrl & FC_DTRDSR) != 0);
   dcb.fOutxDsrFlow = bSet;
   if(bSet)
      dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
   else
      dcb.fDtrControl = DTR_CONTROL_ENABLE;

   bSet = (BYTE)((lpTTY->byFlowCtrl & FC_RTSCTS) != 0);
	dcb.fOutxCtsFlow = bSet;
   if(bSet)
      dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
   else
      dcb.fRtsControl = RTS_CONTROL_ENABLE;

   // setup software flow control
   bSet = (BYTE)((lpTTY->byFlowCtrl & FC_XONXOFF) != 0);

   dcb.fInX = dcb.fOutX = bSet;
   dcb.XonChar = ASCII_XON;
   dcb.XoffChar = ASCII_XOFF;
   dcb.XonLim = 100;
   dcb.XoffLim = 100;

   // other various settings
   dcb.fBinary = TRUE;
   dcb.fParity = TRUE;

   if(!::SetCommState(m_pConn->hCommDev, &dcb))
   {
      ::CloseHandle(m_pConn->hCommDev);
      return FALSE;
   }

   m_pConn->bConnected = TRUE;

   return m_pConn->bConnected;
}



BOOL GCommMonitor::Disconnect()
{
   if(!m_pConn)
      return TRUE;

   // set connected flag to false
   m_pConn->bConnected = FALSE;
   
   // disable event notification and wait for thread to halt
   SetCommMask(m_pConn->hCommDev, 0);

   // block until thread has been halted
   //while(m_pConn->dwThreadID != 0)
   //{
   //   Sleep(10);
   //}

   // drop DTR 
   EscapeCommFunction(m_pConn->hCommDev, CLRDTR);

   // purge any outstanding reads/writes and close device handle
   PurgeComm(m_pConn->hCommDev, PURGE_TXABORT|PURGE_RXABORT|
                                PURGE_TXCLEAR|PURGE_RXCLEAR);

   ::CloseHandle(m_pConn->hCommDev);
   ::CloseHandle(m_pConn->osRead.hEvent);
   ::CloseHandle(m_pConn->osWrite.hEvent);

   return TRUE;
}





BOOL GCommMonitor::Monitor(LPMONITORPROC lpMonitorProc, LPARAM lParam)
{
   BOOL bMonitor = FALSE;

   // create monitoring thread
   if(m_pConn->bConnected)
   {
      if(lpMonitorProc)
      {
         if(!m_hMPP)
         {
            m_hMPP = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(MONITORPROCPARAMS));
            m_pMPP = (LPMONITORPROCPARAMS)::GlobalLock(m_hMPP);
         }

         m_pMPP->lpConn = m_pConn;
         m_pMPP->lpCallback = lpMonitorProc;
         m_pMPP->lpCallbackParam = lParam;

         // create a secondary thread to watch for an event
         DWORD dwThreadID;
         if(::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CommMonitorProc,
                           (LPVOID)m_pMPP, 0, &dwThreadID))
         {
            m_pConn->dwThreadID = dwThreadID;

            ::EscapeCommFunction(m_pConn->hCommDev, SETDTR);
            bMonitor = TRUE;
         }
      }
      else
      {
         ASSERT(FALSE);  // not currently implemented
      }
   }

   return bMonitor;
}








DWORD CALLBACK GCommMonitor::CommMonitorProc(LPVOID lpThreadParameter)
{
   HGLOBAL hParams = (HGLOBAL)lpThreadParameter;
   LPMONITORPROCPARAMS pParams = (LPMONITORPROCPARAMS)::GlobalLock(hParams);
   if(!pParams)
      return 0;
   
   HGLOBAL hBuf = ::GlobalAlloc(GMEM_MOVEABLE, MAX_RXBLOCK + 1);
   if(!hBuf)
   {
      ::GlobalUnlock(hParams);
      return 0;
   }

   LPBYTE lpBuffer = (LPBYTE)::GlobalLock(hBuf);
   if(!lpBuffer)
   {
      ::GlobalUnlock(hParams);
      ::GlobalFree(hBuf);
      return 0;
   }

   // create I/O event used for overlapped read
   OVERLAPPED os;
   ::ZeroMemory(&os, sizeof(os));

   os.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

   if(os.hEvent == NULL || !SetCommMask(pParams->lpConn->hCommDev, EV_RXCHAR))
   {
      ReportLastError();
      return 0;
   }

   while(pParams->lpConn->bConnected)
   {
      DWORD dwEvtMask = 0;
      int nLength = 0;

      OVERLAPPED ol;
      ::ZeroMemory(&ol, sizeof(ol));
      ol.hEvent = os.hEvent;

      WaitCommEvent(pParams->lpConn->hCommDev, &dwEvtMask, &ol);

      if((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
      {
         do
         {
            if((nLength = CommReadBlock(pParams->lpConn, lpBuffer, MAX_RXBLOCK)) != 0)
            {
               if(pParams->lpCallback)
                  pParams->lpCallback(hBuf, nLength, pParams->lpCallbackParam);
            }

         } while(nLength > 0);
      }
   }

   ::GlobalUnlock(hBuf);
   ::GlobalFree(hBuf);

   // get rid of event handles
   ::CloseHandle(os.hEvent);

   // clear information in structure (indicates the thread has terminated)
   pParams->lpConn->dwThreadID = NULL;

   ::GlobalUnlock(hParams);
   return 1;
}





BOOL CALLBACK GCommMonitor::CommReadBlock(LPCONNECTION lpConn, LPBYTE lpszBlock, 
                                                                          int nLen)
{
   // only try to read number of bytes in queue
   DWORD dwErrorFlags;
   COMSTAT ComStat;

   ::ClearCommError(lpConn->hCommDev, &dwErrorFlags, &ComStat);
   DWORD dwLength = min((DWORD)nLen, ComStat.cbInQue);

   if(dwLength > 0)
   {
      BOOL bReadStat = ReadFile(lpConn->hCommDev, lpszBlock, dwLength,
                                &dwLength, &lpConn->osRead);

      if(!bReadStat)
      {
         if(GetLastError() == ERROR_IO_PENDING)
         {
            OutputDebugString("\n\rIO Pending");
            // we have to wait for read to complete.  This function will timeout
            // according to the CommTimeOuts.ReadTotalTimeoutConstant variable
            // Every time it times out, check for port errors
            while(!GetOverlappedResult(lpConn->hCommDev, &lpConn->osRead,
                                       &dwLength, TRUE))
            {
               DWORD dwError = GetLastError();
               if(dwError == ERROR_IO_INCOMPLETE)
               {
                  // normal result if not finished
                  continue;
               }
               else
               {
                  // CAN DISPLAY ERROR MESSAGE HERE
                  // an error occured, try to recover
                  ::ClearCommError(lpConn->hCommDev, &dwErrorFlags, &ComStat);
                  if(dwErrorFlags > 0)
                  {
                     // CAN DISPLAY ERROR MESSAGE HERE
                  }

                  break;
               }
            }
            
         }
         else
         {
            // some other error occured
            dwLength = 0;
            ClearCommError(lpConn->hCommDev, &dwErrorFlags, &ComStat);
            if(dwErrorFlags > 0)
            {
               // CAN DISPLAY ERROR MESSAGE HERE
            }
         }
      }
   }

   return dwLength;
}





⌨️ 快捷键说明

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