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

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

 相关链接:

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

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

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

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

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

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

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

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

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

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

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

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

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

开源 C# 快速开发(十四)进程--内存映射

开源 C# 快速开发(十五)进程--windows消息

开源 C# 快速开发(十六)数据库--sqlserver增删改查

推荐链接:

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

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

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

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

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

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

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

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

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

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

目录:

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<string>(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<string>(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<string>(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<string>(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;
        }
    }
}

三、效果演示

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值