当前位置: 首页 > news >正文

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

         文章的目的为了记录使用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<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;}}
}

三、效果演示

http://www.dtcms.com/a/427260.html

相关文章:

  • 甲流防治的新思路:基于肠道菌群的调节策略
  • 深圳网站建设fantodops做电商网站流程
  • 阿里云个人备案可以做企业网站代理办公司注册大概多少钱
  • Flink 架构组件、任务链路、Slot 资源与集群形态
  • 无人机图传及组网功能如何实现?适用频段与传输模块选择全攻略
  • 从“如何画”到“为何画”:AIGC倒逼UI设计师回归设计本源
  • 优化 Flink 基于状态的 ETL少 Shuffle、不膨胀、可落地的工程
  • flink执行图
  • 在线酒店预定网站制作长春站建筑
  • wordpress购物网站教程普陀区建设局网站
  • TCP抓包实验
  • spring boot项目使用tomcat发布,也可以使用Undertow(理论)
  • 【Linux-2】字符设备编写不同模板
  • 基于 Web3 + RWA 的品牌门店数字化范式
  • 惠州 网站建设公司简单制作网页
  • Gartner 2025 中国网络安全成熟度曲线深度解读:AI 安全如何重构防御逻辑
  • 为男人做购物网站超详细wordpress常用函数
  • 【C++ 语法】模板进阶
  • 【K8s】K8s的声明式API核心
  • 关于网站开发人员保密协议专业服务网站开发
  • supabase 实现聊天板(Chat Board)
  • PersistentVolume + NFS:网络共享存储
  • leetcode 1863 找出所有子集的异或总和再求和
  • 【C++】STL -- vector 的使用及模拟实现
  • 网站如何做图片特效erp软件实施
  • 【28】C# WinForm入门到精通 ——多文档窗体MDI【属性、方法、实例、源码】【多窗口重叠、水平平铺、垂直平铺、窗体传值】
  • 贡井区建设局网站淘宝客做自己的网站
  • 蓝牙发展史
  • 对LED点灯实验的C与汇编的深入分析,提及到volatile
  • 网站建设外包广州网站建设说说外链的建设