首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 命名管道通訊實戰:本地進程間輕量級 IPC 完整實現

     編輯:關於C++

前言

在本地進程間通訊 (IPC) 中,Socket 雖然通用但開銷較大。Windows 命名管道 提供了高效、可靠、雙向的通訊機制,適合輕量級本地 IPC。本文完整呈現基於 MFC 的命名管道伺服器端實現,涵蓋核心 API、類別設計、執行緒模型與實戰代碼。

一、核心 Windows API 速查

API用途關鍵參數
CreateNamedPipe伺服器建立管道管道名、雙向/單向、阻塞/非阻塞、實例數、緩衝區大小
ConnectNamedPipe等待客戶端連線管道句柄、Overlapped 結構 (非同步)
CreateFile客戶端開啟管道管道名、存取模式、共享模式、建立方式
WriteFile/ReadFile資料收發緩衝區、位元組數、Overlapped (非同步)
DisconnectNamedPipe斷開連線管道句柄
WaitNamedPipe客戶端等待管道可用管道名、超時時間

二、伺服器端架構設計

1. 基類 CMyPipe - 管道核心屬性


#pragma once
class CMyPipe {
public:
    CMyPipe();
    CMyPipe(LPCTSTR lpctstr);  // 管道名稱重載
    ~CMyPipe();

protected:
    HANDLE MyPipe;       // 管道句柄
    CString MyPipeName;  // 管道名稱 (格式:\\.\pipe\name)
};

2. 擴展類 CPipeServer - 伺服器業務邏輯

  • 多實例支援:動態陣列 CPipeServer* m_pPipeServer
  • 非同步執行緒:AfxBeginThread 啟動 ServerReadProc
  • 視窗整合:CWnd* 回呼顯示接收訊息
  • 生命週期管理:InitPipeServer/UnInitPipeServer

三、關鍵實現細節

1. 管道建立與非同步讀取


bool CPipeServer::ServerReplyInfo(CString StrReply) {
    MyPipe = CreateNamedPipe(MyPipeName,
        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,  // 雙向 + 非同步
        PIPE_TYPE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        256, 256,  // 輸出/輸入緩衝區
        NULL, NULL);
    
    if (MyPipe != INVALID_HANDLE_VALUE) {
        m_StrReply = StrReply;
        m_pWinThread = AfxBeginThread(ServerReadProc, (LPVOID)this);
        return true;
    }
    return false;
}

2. 背景執行緒讀取迴圈


UINT CPipeServer::ServerReadProc(LPVOID lParam) {
    CPipeServer* pPipeServer = (CPipeServer*)lParam;
    TCHAR buffer[256];
    DWORD dwRead, dwWritten;
    
    while (ConnectNamedPipe(pPipeServer->MyPipe, NULL)) {
        while (ReadFile(pPipeServer->MyPipe, buffer, 256*sizeof(TCHAR), &dwRead, NULL)) {
            if (dwRead == 0) break;
            if (_tcscmp(buffer, _T("exit")) == 0) {  // 關閉指令
                DisconnectNamedPipe(pPipeServer->MyPipe);
                CloseHandle(pPipeServer->MyPipe);
                return 0;
            }
            // 顯示到 UI 列表框
            if (pPipeServer->m_pWndServer) {
                ((CListBox*)pPipeServer->m_pWndServer->GetDlgItem(IDC_LBCONTENT))
                    ->InsertString(0, buffer);
            }
            // 回應客戶端
            _tcscpy(buffer, pPipeServer->m_StrReply);
            WriteFile(pPipeServer->MyPipe, buffer, (_tcslen(buffer)+1)*sizeof(TCHAR), &dwWritten, NULL);
        }
        DisconnectNamedPipe(pPipeServer->MyPipe);
    }
    CloseHandle(pPipeServer->MyPipe);
    return 0;
}

3. 伺服器啟動/關閉控制


void CMyDialog::OnBnClickedBtnconnect() {
    CPipeServer* pPipeServer = (CPipeServer*)this;
    CString caption;
    GetDlgItem(IDC_BTNCONNECT)->GetWindowText(caption);
    
    if (caption == _T("連接")) {
        for (UINT i = 0; i < pPipeServer->m_InstanceCount; ++i) {
            pPipeServer->m_pPipeServer[i].SethWndServer(this);
            pPipeServer->m_pPipeServer[i].ServerReplyInfo(_T("伺服器應答!"));
        }
        GetDlgItem(IDC_BTNCONNECT)->SetWindowText(_T("斷開"));
    } else {
        for (UINT i = 0; i < pPipeServer->m_InstanceCount; ++i)
            pPipeServer->m_pPipeServer[i].ServerExit();
        GetDlgItem(IDC_BTNCONNECT)->SetWindowText(_T("連接"));
    }
}

四、註冊表協議關聯 (啟動應用程式)

參考 QQ tencent:// 協議,可註冊自定義 URI Scheme 啟動本地程式:


Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\MyApp]
@="MyApp Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\MyApp\shell\open\command]
@="\"D:\\Path\\MyApp.exe\" \"%1\""

網頁中 `` 點擊即啟動程式並傳遞參數。

五、總結與最佳實務

  • 命名管道適合本地高頻、低延遲雙向通訊
  • 使用 FILE_FLAG_OVERLAPPED + 執行緒池實現高併發
  • 管道名格式固定:\\.\pipe\name (本機) 或 \\Server\pipe\name (跨網路)
  • 錯誤處理:檢查 INVALID_HANDLE_VALUE、GetLastError()
  • 資源清理:確保 CloseHandle、DisconnectNamedPipe 成對呼叫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved