代码改变世界

开源 C# 飞快研发(十三)进程--管道通讯

2025-10-02 21:39  tlnshuju  阅读(14)  评论(0)    收藏  举报

         文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

 相关链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

开源 C# 快速开发(十一)线程

开源 C# 快速开发(十二)进程监控

推荐链接:

开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客

开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客

开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客

开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客

本章节主要内容是:进程之间的命名管道服务器和客户端程序。

目录:

1.源码分析

2.所有源码

3.效果演示

一、源码分析

架构设计分析
1. 整体架构

┌─────────────────┐   命名管道通信    ┌─────────────────┐
│   服务端程序    │ ←─────────────→  │   客户端程序    │
│                 │                  │                 │
│ - 管道服务器    │                  │ - 管道客户端    │
│ - 消息监听      │                  │ - 消息发送      │
│ - 连接管理      │                  │ - 连接管理      │
└─────────────────┘                  └─────────────────┘
2. 通信流程

服务端启动 → 监听连接 → 客户端连接 → 建立通信通道 → 双向消息传递
核心技术实现分析
服务端核心代码分析
1. 管道服务器初始化

pipeServer = new NamedPipeServerStream(
    "TestPipe",              // 管道名称
    PipeDirection.InOut,     // 双向通信
    1,                       // 最大实例数
    PipeTransmissionMode.Message, // 消息模式
    PipeOptions.Asynchronous      // 异步操作
);


关键参数说明:

PipeDirection.InOut: 支持双向通信

最大实例数1: 只允许一个客户端连接

Message模式: 以消息为单位传输,保持消息边界

Asynchronous: 支持异步操作,提高性能

2. 连接处理循环

while (!cancellationToken.IsCancellationRequested)
{
    pipeServer.WaitForConnection();  // 阻塞等待客户端连接
    LogStatus("客户端已连接");
    // 启动消息接收任务
    Task.Run(() => ReceiveMessages(cancellationToken));
    // 保持连接状态
    while (pipeServer.IsConnected && !cancellationToken.IsCancellationRequested)
    {
        Thread.Sleep(100);
    }
}


设计优点:

使用CancellationToken支持优雅停止

分离连接管理和消息处理

自动重连机制


3. 消息接收机制

private async void ReceiveMessages(CancellationToken cancellationToken)
{
    byte[] buffer = new byte[1024];
    StringBuilder messageBuilder = new StringBuilder();
    while (pipeServer.IsConnected && !cancellationToken.IsCancellationRequested)
    {
        int bytesRead = await pipeServer.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
        if (bytesRead > 0)
        {
            string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            messageBuilder.Append(receivedData);
            // 消息完整性检查
            if (receivedData.EndsWith("\n") || !pipeServer.IsMessageComplete)
            {
                string completeMessage = messageBuilder.ToString().Trim();
                LogMessage($"客户端: {completeMessage}");
                messageBuilder.Clear();
            }
        }
    }
}


二、所有源码

NamedPipeServer.cs  服务器端源码

using System;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NamedPipeServer
{
    public partial class ServerForm : Form
    {
        private NamedPipeServerStream pipeServer;
        private CancellationTokenSource cancellationTokenSource;
        private bool isListening = false;
        public ServerForm()
        {
            InitializeComponent();
            InitializeControls();
        }
        private void InitializeControls()
        {
            // 窗体设置
            this.Text = "命名管道服务端";
            this.Size = new System.Drawing.Size(500, 400);
            this.StartPosition = FormStartPosition.CenterScreen;
            // 创建控件
            var lblStatus = new Label { Text = "服务状态:", Location = new System.Drawing.Point(20, 20), AutoSize = true };
            var lblLog = new Label { Text = "通信日志:", Location = new System.Drawing.Point(20, 180), AutoSize = true };
            txtStatus = new TextBox
            {
                Location = new System.Drawing.Point(20, 50),
                Size = new System.Drawing.Size(440, 100),
                Multiline = true,
                ReadOnly = true,
                ScrollBars = ScrollBars.Vertical
            };
            txtLog = new TextBox
            {
                Location = new System.Drawing.Point(20, 210),
                Size = new System.Drawing.Size(440, 100),
                Multiline = true,
                ReadOnly = true,
                ScrollBars = ScrollBars.Vertical
            };
            txtMessage = new TextBox { Location = new System.Drawing.Point(20, 320), Size = new System.Drawing.Size(300, 23) };
            btnStart = new Button { Text = "启动服务", Location = new System.Drawing.Point(20, 140), Size = new System.Drawing.Size(80, 30) };
            btnStop = new Button { Text = "停止服务", Location = new System.Drawing.Point(110, 140), Size = new System.Drawing.Size(80, 30), Enabled = false };
            btnSend = new Button { Text = "发送消息", Location = new System.Drawing.Point(330, 320), Size = new System.Drawing.Size(80, 30) };
            // 添加到窗体
            this.Controls.AddRange(new Control[] { lblStatus, lblLog, txtStatus, txtLog, txtMessage, btnStart, btnStop, btnSend });
            // 事件绑定
            btnStart.Click += BtnStart_Click;
            btnStop.Click += BtnStop_Click;
            btnSend.Click += BtnSend_Click;
            this.FormClosing += ServerForm_FormClosing;
        }
        // 控件声明
        private TextBox txtStatus;
        private TextBox txtLog;
        private TextBox txtMessage;
        private Button btnStart;
        private Button btnStop;
        private Button btnSend;
        private async void BtnStart_Click(object sender, EventArgs e)
        {
            try
            {
                cancellationTokenSource = new CancellationTokenSource();
                isListening = true;
                btnStart.Enabled = false;
                btnStop.Enabled = true;
                btnSend.Enabled = true;
                LogStatus("服务启动中...");
                // 启动管道监听
                await Task.Run(() => StartPipeServer(cancellationTokenSource.Token));
            }
            catch (Exception ex)
            {
                LogStatus($"启动服务失败: {ex.Message}");
                ResetControls();
            }
        }
        private void BtnStop_Click(object sender, EventArgs e)
        {
            StopServer();
        }
        private void BtnSend_Click(object sender, EventArgs e)
        {
            SendMessageToClient();
        }
        private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopServer();
        }
        private void StartPipeServer(CancellationToken cancellationToken)
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    LogStatus("等待客户端连接...");
                    // 创建命名管道服务器
                    pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, 1,
                                                         PipeTransmissionMode.Message, PipeOptions.Asynchronous);
                    // 等待客户端连接
                    pipeServer.WaitForConnection();
                    LogStatus("客户端已连接");
                    LogMessage("系统: 客户端连接成功");
                    // 启动消息接收循环
                    Task.Run(() => ReceiveMessages(cancellationToken));
                    // 保持连接直到客户端断开
                    while (pipeServer.IsConnected && !cancellationToken.IsCancellationRequested)
                    {
                        Thread.Sleep(100);
                    }
                    if (pipeServer.IsConnected)
                    {
                        pipeServer.Disconnect();
                    }
                    pipeServer.Close();
                    pipeServer.Dispose();
                    LogMessage("系统: 客户端断开连接");
                }
            }
            catch (Exception ex)
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    LogStatus($"服务器错误: {ex.Message}");
                }
            }
        }
        private async void ReceiveMessages(CancellationToken cancellationToken)
        {
            byte[] buffer = new byte[1024];
            StringBuilder messageBuilder = new StringBuilder();
            try
            {
                while (pipeServer.IsConnected && !cancellationToken.IsCancellationRequested)
                {
                    if (pipeServer.IsConnected && pipeServer.CanRead)
                    {
                        int bytesRead = await pipeServer.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                        if (bytesRead > 0)
                        {
                            string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                            messageBuilder.Append(receivedData);
                            // 检查是否收到完整消息(以换行符结尾)
                            if (receivedData.EndsWith("\n") || !pipeServer.IsMessageComplete)
                            {
                                string completeMessage = messageBuilder.ToString().Trim();
                                if (!string.IsNullOrEmpty(completeMessage))
                                {
                                    LogMessage($"客户端: {completeMessage}");
                                }
                                messageBuilder.Clear();
                            }
                        }
                    }
                    await Task.Delay(10, cancellationToken);
                }
            }
            catch (Exception ex)
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    LogMessage($"系统: 接收消息错误 - {ex.Message}");
                }
            }
        }
        private void SendMessageToClient()
        {
            if (string.IsNullOrWhiteSpace(txtMessage.Text))
                return;
            if (pipeServer == null || !pipeServer.IsConnected)
            {
                MessageBox.Show("客户端未连接", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            try
            {
                string message = txtMessage.Text + "\n";
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                pipeServer.Write(buffer, 0, buffer.Length);
                pipeServer.Flush();
                LogMessage($"服务端: {txtMessage.Text}");
                txtMessage.Clear();
            }
            catch (Exception ex)
            {
                LogMessage($"系统: 发送消息失败 - {ex.Message}");
            }
        }
        private void StopServer()
        {
            try
            {
                isListening = false;
                cancellationTokenSource?.Cancel();
                if (pipeServer != null)
                {
                    if (pipeServer.IsConnected)
                    {
                        pipeServer.Disconnect();
                    }
                    pipeServer.Close();
                    pipeServer.Dispose();
                    pipeServer = null;
                }
                LogStatus("服务已停止");
                ResetControls();
            }
            catch (Exception ex)
            {
                LogStatus($"停止服务时出错: {ex.Message}");
            }
        }
        private void LogStatus(string message)
        {
            if (txtStatus.InvokeRequired)
            {
                txtStatus.Invoke(new Action(LogStatus), message);
                return;
            }
            txtStatus.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
            txtStatus.ScrollToCaret();
        }
        private void LogMessage(string message)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke(new Action(LogMessage), message);
                return;
            }
            txtLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
            txtLog.ScrollToCaret();
        }
        private void ResetControls()
        {
            if (btnStart.InvokeRequired)
            {
                btnStart.Invoke(new Action(ResetControls));
                return;
            }
            btnStart.Enabled = true;
            btnStop.Enabled = false;
            btnSend.Enabled = false;
        }
    }
}

NamedPipeClient.cs 客户端源码

using System;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NamedPipeClient
{
    public partial class ClientForm : Form
    {
        private NamedPipeClientStream pipeClient;
        private CancellationTokenSource cancellationTokenSource;
        private bool isConnected = false;
        public ClientForm()
        {
            InitializeComponent();
            InitializeControls();
        }
        private void InitializeControls()
        {
            // 窗体设置
            this.Text = "命名管道客户端";
            this.Size = new System.Drawing.Size(500, 400);
            this.StartPosition = FormStartPosition.CenterScreen;
            // 创建控件
            var lblStatus = new Label { Text = "连接状态:", Location = new System.Drawing.Point(20, 20), AutoSize = true };
            var lblLog = new Label { Text = "通信日志:", Location = new System.Drawing.Point(20, 180), AutoSize = true };
            txtStatus = new TextBox
            {
                Location = new System.Drawing.Point(20, 50),
                Size = new System.Drawing.Size(440, 100),
                Multiline = true,
                ReadOnly = true,
                ScrollBars = ScrollBars.Vertical
            };
            txtLog = new TextBox
            {
                Location = new System.Drawing.Point(20, 210),
                Size = new System.Drawing.Size(440, 100),
                Multiline = true,
                ReadOnly = true,
                ScrollBars = ScrollBars.Vertical
            };
            txtMessage = new TextBox { Location = new System.Drawing.Point(20, 320), Size = new System.Drawing.Size(300, 23) };
            btnConnect = new Button { Text = "连接服务", Location = new System.Drawing.Point(20, 140), Size = new System.Drawing.Size(80, 30) };
            btnDisconnect = new Button { Text = "断开连接", Location = new System.Drawing.Point(110, 140), Size = new System.Drawing.Size(80, 30), Enabled = false };
            btnSend = new Button { Text = "发送消息", Location = new System.Drawing.Point(330, 320), Size = new System.Drawing.Size(80, 30), Enabled = false };
            // 添加到窗体
            this.Controls.AddRange(new Control[] { lblStatus, lblLog, txtStatus, txtLog, txtMessage, btnConnect, btnDisconnect, btnSend });
            // 事件绑定
            btnConnect.Click += BtnConnect_Click;
            btnDisconnect.Click += BtnDisconnect_Click;
            btnSend.Click += BtnSend_Click;
            this.FormClosing += ClientForm_FormClosing;
        }
        // 控件声明
        private TextBox txtStatus;
        private TextBox txtLog;
        private TextBox txtMessage;
        private Button btnConnect;
        private Button btnDisconnect;
        private Button btnSend;
        private async void BtnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                cancellationTokenSource = new CancellationTokenSource();
                btnConnect.Enabled = false;
                btnDisconnect.Enabled = true;
                btnSend.Enabled = true;
                LogStatus("正在连接服务器...");
                await Task.Run(() => ConnectToServer(cancellationTokenSource.Token));
            }
            catch (Exception ex)
            {
                LogStatus($"连接失败: {ex.Message}");
                ResetControls();
            }
        }
        private void BtnDisconnect_Click(object sender, EventArgs e)
        {
            Disconnect();
        }
        private void BtnSend_Click(object sender, EventArgs e)
        {
            SendMessageToServer();
        }
        private void ClientForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Disconnect();
        }
        private void ConnectToServer(CancellationToken cancellationToken)
        {
            try
            {
                pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut, PipeOptions.Asynchronous);
                LogStatus("尝试连接服务器...");
                pipeClient.Connect(5000); // 5秒超时
                if (pipeClient.IsConnected)
                {
                    isConnected = true;
                    LogStatus("已成功连接到服务器");
                    LogMessage("系统: 连接到服务器成功");
                    // 启动消息接收循环
                    Task.Run(() => ReceiveMessages(cancellationToken));
                }
                else
                {
                    throw new Exception("连接超时或失败");
                }
            }
            catch (TimeoutException)
            {
                throw new Exception("连接超时,请确保服务器正在运行");
            }
            catch (Exception ex)
            {
                throw new Exception($"连接错误: {ex.Message}");
            }
        }
        private async void ReceiveMessages(CancellationToken cancellationToken)
        {
            byte[] buffer = new byte[1024];
            StringBuilder messageBuilder = new StringBuilder();
            try
            {
                while (isConnected && !cancellationToken.IsCancellationRequested)
                {
                    if (pipeClient.IsConnected && pipeClient.CanRead)
                    {
                        int bytesRead = await pipeClient.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                        if (bytesRead > 0)
                        {
                            string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                            messageBuilder.Append(receivedData);
                            // 检查是否收到完整消息
                            if (receivedData.EndsWith("\n") || !pipeClient.IsMessageComplete)
                            {
                                string completeMessage = messageBuilder.ToString().Trim();
                                if (!string.IsNullOrEmpty(completeMessage))
                                {
                                    LogMessage($"服务端: {completeMessage}");
                                }
                                messageBuilder.Clear();
                            }
                        }
                    }
                    await Task.Delay(10, cancellationToken);
                }
            }
            catch (Exception ex)
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    LogMessage($"系统: 接收消息错误 - {ex.Message}");
                }
            }
        }
        private void SendMessageToServer()
        {
            if (string.IsNullOrWhiteSpace(txtMessage.Text))
                return;
            if (pipeClient == null || !pipeClient.IsConnected)
            {
                MessageBox.Show("未连接到服务器", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            try
            {
                string message = txtMessage.Text + "\n";
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                pipeClient.Write(buffer, 0, buffer.Length);
                pipeClient.Flush();
                LogMessage($"客户端: {txtMessage.Text}");
                txtMessage.Clear();
            }
            catch (Exception ex)
            {
                LogMessage($"系统: 发送消息失败 - {ex.Message}");
            }
        }
        private void Disconnect()
        {
            try
            {
                isConnected = false;
                cancellationTokenSource?.Cancel();
                if (pipeClient != null)
                {
                    if (pipeClient.IsConnected)
                    {
                        pipeClient.Close();
                    }
                    pipeClient.Dispose();
                    pipeClient = null;
                }
                LogStatus("已断开连接");
                ResetControls();
            }
            catch (Exception ex)
            {
                LogStatus($"断开连接时出错: {ex.Message}");
            }
        }
        private void LogStatus(string message)
        {
            if (txtStatus.InvokeRequired)
            {
                txtStatus.Invoke(new Action(LogStatus), message);
                return;
            }
            txtStatus.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
            txtStatus.ScrollToCaret();
        }
        private void LogMessage(string message)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke(new Action(LogMessage), message);
                return;
            }
            txtLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
            txtLog.ScrollToCaret();
        }
        private void ResetControls()
        {
            if (btnConnect.InvokeRequired)
            {
                btnConnect.Invoke(new Action(ResetControls));
                return;
            }
            btnConnect.Enabled = true;
            btnDisconnect.Enabled = false;
            btnSend.Enabled = false;
        }
    }
}

三、效果演示