C# 两个进程/exe通讯方式 两个应用程序通讯方式
C# 两个exe通讯方式 两个应用程序通讯方式
1. 命名管道(Named Pipes)
1.1. 概述
命名管道是一种用于在同一台机器或网络中不同进程之间进行双向通信的机制。它支持同步和异步通信,适用于需要高效数据传输的场景。
1.2. 特点
双向通信:支持双向数据传输。
安全性:可以设置访问权限,确保通信的安全性。
跨网络:支持跨网络通信。
1.3. 实现方式
1.3.1. 服务器端(NamedPipeServerStream)
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;class PipeServer
{public static async Task StartServer(){using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)){Console.WriteLine("等待客户端连接...");await pipeServer.WaitForConnectionAsync();Console.WriteLine("客户端已连接。");// 接收数据byte[] buffer = new byte[256];int bytesRead = await pipeServer.ReadAsync(buffer, 0, buffer.Length);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到消息:{receivedMessage}");// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);await pipeServer.WriteAsync(responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}}static void Main(string[] args){Task.Run(() => StartServer()).Wait();}
}
1.3.2. 客户端(NamedPipeClientStream)
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;class PipeClient
{public static async Task StartClient(){using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut, PipeOptions.Asynchronous)){Console.WriteLine("尝试连接到服务器...");await pipeClient.ConnectAsync();Console.WriteLine("已连接到服务器。");// 发送数据string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);await pipeClient.WriteAsync(messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 接收回应byte[] buffer = new byte[256];int bytesRead = await pipeClient.ReadAsync(buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到回应:{response}");}}static void Main(string[] args){Task.Run(() => StartClient()).Wait();}
}
1.4. 使用场景
需要高效、双向通信的应用程序。
同一台机器或网络中的进程间通信。
需要传输大量数据或复杂数据结构。
2. 套接字(Sockets)
2.1. 概述
套接字是一种底层的通信机制,支持跨网络的进程间通信。它适用于需要跨不同机器或网络通信的应用程序。
2.2. 特点
灵活性高:支持多种协议(TCP、UDP)。
跨平台:可用于不同操作系统间的通信。
高性能:适用于实时数据传输和高并发应用。
2.3. 实现方式
2.3.1. 服务器端(TCP)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class SocketServer
{public static async Task StartServer(){TcpListener listener = new TcpListener(IPAddress.Any, 5000);listener.Start();Console.WriteLine("服务器已启动,等待连接...");using (TcpClient client = await listener.AcceptTcpClientAsync()){Console.WriteLine("客户端已连接。");NetworkStream stream = client.GetStream();// 接收数据byte[] buffer = new byte[1024];int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到消息:{receivedMessage}");// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);await stream.WriteAsync(responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}listener.Stop();}static void Main(string[] args){Task.Run(() => StartServer()).Wait();}
}
2.3.2. 客户端(TCP)
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class SocketClient
{public static async Task StartClient(){using (TcpClient client = new TcpClient()){Console.WriteLine("尝试连接到服务器...");await client.ConnectAsync("127.0.0.1", 5000);Console.WriteLine("已连接到服务器。");NetworkStream stream = client.GetStream();// 发送数据string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);await stream.WriteAsync(messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 接收回应byte[] buffer = new byte[1024];int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到回应:{response}");}}static void Main(string[] args){Task.Run(() => StartClient()).Wait();}
}
2.4. 使用场景
需要跨不同机器或网络通信的应用程序。
实时通信,如聊天应用、游戏服务器等。
需要灵活控制通信协议和数据格式的场景。
3. 内存映射文件(Memory-Mapped Files)
3.1. 概述
内存映射文件允许多个进程共享同一块内存区域,实现高效的数据交换。它适用于需要频繁、快速共享大量数据的场景。
3.2. 特点
高性能:通过共享内存实现快速数据交换。
简单的数据共享:适用于需要在多个进程间共享复杂数据结构的应用程序。
跨语言支持:不同编程语言的进程可以通过内存映射文件进行通信。
3.3. 实现方式
3.3.1. 创建内存映射文件(服务器端)
using System;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading;class MemoryMappedFileServer
{static void Main(string[] args){using (var mmf = MemoryMappedFile.CreateOrOpen("SharedMemory", 1024)){Console.WriteLine("服务器已启动,等待消息...");using (var accessor = mmf.CreateViewAccessor()){while (true){byte[] buffer = new byte[256];accessor.ReadArray(0, buffer, 0, buffer.Length);string message = Encoding.UTF8.GetString(buffer).TrimEnd('\0');if (!string.IsNullOrEmpty(message)){Console.WriteLine($"收到消息:{message}");// 清空消息accessor.WriteArray(0, new byte[256], 0, 256);// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);accessor.WriteArray(0, responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}Thread.Sleep(1000); // 等待一段时间再检查}}}}
}
3.3.2. 读取内存映射文件(客户端)
using System;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading.Tasks;class MemoryMappedFileClient
{static async Task Main(string[] args){using (var mmf = MemoryMappedFile.OpenExisting("SharedMemory")){using (var accessor = mmf.CreateViewAccessor()){// 发送消息string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);accessor.WriteArray(0, messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 等待回应while (true){byte[] buffer = new byte[256];accessor.ReadArray(0, buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer).TrimEnd('\0');if (!string.IsNullOrEmpty(response)){Console.WriteLine($"收到回应:{response}");// 清空回应accessor.WriteArray(0, new byte[256], 0, 256);break;}await Task.Delay(500);}}}}
}
3.4. 使用场景
需要在多个进程间高效共享大量数据。
实时数据交换,如视频流、实时监控数据等。
复杂数据结构的共享,如图像数据、结构化信息等。
4. 信号和消息(Windows Messages)
4.1. 概述
在 Windows 环境下,进程可以通过发送和接收窗口消息来进行通信。这种方法通常用于 GUI 应用程序之间的简单通信。
4.2. 特点
适用于 GUI 应用:主要用于具有窗口的应用程序之间的通信。
简单实现:适合于发送简单的消息或命令。
4.3. 实现方式
4.3.1. 发送消息(发送方)
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;class MessageSender
{// 引入 SendMessage 函数[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;static void Main(string[] args){// 获取目标窗口句柄,可以通过窗口标题查找IntPtr hWnd = FindWindow(null, "接收消息的窗口标题");if (hWnd != IntPtr.Zero){string message = "Hello from sender!";byte[] msgBytes = Encoding.UTF8.GetBytes(message);IntPtr lParam = Marshal.AllocHGlobal(msgBytes.Length + 1);Marshal.Copy(msgBytes, 0, lParam, msgBytes.Length);Marshal.WriteByte(lParam, msgBytes.Length, 0); // 添加 null 终止符SendMessage(hWnd, WM_CUSTOM, IntPtr.Zero, lParam);Marshal.FreeHGlobal(lParam);Console.WriteLine("已发送消息。");}else{Console.WriteLine("未找到目标窗口。");}}// 引入 FindWindow 函数[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
4.3.2. 接收消息(接收方)
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;class MessageReceiver : Form
{// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 引入 WndProcprotected override void WndProc(ref Message m){if (m.Msg == WM_CUSTOM){// 获取消息内容int length = 0;while (Marshal.ReadByte(m.LParam, length) != 0) length++;byte[] buffer = new byte[length];Marshal.Copy(m.LParam, buffer, 0, length);string receivedMessage = Encoding.UTF8.GetString(buffer);MessageBox.Show($"收到消息:{receivedMessage}");}base.WndProc(ref m);}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new MessageReceiver());}
}
4.4. 使用场景
简单的 GUI 应用程序之间的通信。
发送简单的命令或通知。
不需要高性能或大量数据传输的场景。
5. 内存映射数据结构(Memory-Mapped Data Structures)
5.1. 概述
除了简单的数据交换,进程间还可以共享复杂的数据结构,如对象、数组等。通过内存映射文件,可以实现多个进程共享相同的内存空间,进而共享数据结构。
5.2. 特点
高效数据共享:适用于需要共享复杂数据结构的场景。
实时更新:数据在共享内存中实时更新,适用于需要实时同步数据的应用。
5.3. 实现方式
5.3.1. 共享类库
创建一个共享的类库,定义数据结构,并确保它们在内存映射文件中正确对齐和序列化。
5.3.2. 服务器端(共享数据写入)
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;class SharedData
{[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]public string Message;
}class MemoryMappedFileServer
{static void Main(string[] args){using (var mmf = MemoryMappedFile.CreateOrOpen("SharedData", Marshal.SizeOf(typeof(SharedData)))){using (var accessor = mmf.CreateViewAccessor()){SharedData data = new SharedData { Message = "Hello from server!" };accessor.Write(0, ref data);Console.WriteLine("已写入共享数据。");}Console.WriteLine("按任意键退出...");Console.ReadKey();}}
}
5.3.3. 客户端(共享数据读取)
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;class SharedData
{[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]public string Message;
}class MemoryMappedFileClient
{static void Main(string[] args){using (var mmf = MemoryMappedFile.OpenExisting("SharedData")){using (var accessor = mmf.CreateViewAccessor()){SharedData data = new SharedData();accessor.Read(0, ref data);Console.WriteLine($"收到共享数据:{data.Message}");}}}
}
5.4. 使用场景
需要共享复杂数据结构或大量数据的进程间通信。
实时数据同步,如监控系统、实时数据分析等。
6. Windows Communication Foundation (WCF)
6.1. 概述
WCF 是一个用于构建服务导向应用程序的框架,支持多种传输协议和消息格式。它适用于需要跨平台、跨网络通信的复杂应用程序。
6.2. 特点
多协议支持:支持 HTTP, TCP, Named Pipes 等多种传输协议。
灵活性高:可配置性强,适用于不同的通信需求。
安全性:内置多种安全机制,如消息加密、身份验证等。
6.3. 实现方式
6.3.1. 定义服务契约
using System.ServiceModel;[ServiceContract]
public interface IMyService
{[OperationContract]string GetMessage(string name);
}
6.3.2. 实现服务
public class MyService : IMyService
{public string GetMessage(string name){return $"Hello, {name}!";}
}
6.3.3. 配置服务
App.config(服务器端)
<configuration><system.serviceModel><services><service name="MyService"><endpoint address="" binding="netNamedPipeBinding" contract="IMyService" /><host><baseAddresses><add baseAddress="net.pipe://localhost/MyService" /></baseAddresses></host></service></services><bindings><netNamedPipeBinding><binding name="NamedPipeBinding" /></netNamedPipeBinding></bindings></system.serviceModel>
</configuration>
6.3.4. 启动服务
using System;
using System.ServiceModel;class Program
{static void Main(string[] args){using (ServiceHost host = new ServiceHost(typeof(MyService))){host.Open();Console.WriteLine("服务已启动。按任意键退出...");Console.ReadKey();}}
}
6.3.5. 客户端调用
using System;
using System.ServiceModel;class Program
{static void Main(string[] args){var binding = new NetNamedPipeBinding();var endpoint = new EndpointAddress("net.pipe://localhost/MyService");ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>(binding, endpoint);IMyService proxy = factory.CreateChannel();string response = proxy.GetMessage("Client");Console.WriteLine($"服务器回应:{response}");((IClientChannel)proxy).Close();factory.Close();}
}
6.4. 使用场景
需要跨网络或跨平台的复杂服务通信。
需要高级的安全性和可靠性。
构建服务导向架构(Service-Oriented Architecture, SOA)的应用程序。
7. 信号R(SignalR)
7.1. 概述
SignalR 是一个用于构建实时 Web 功能的库,虽然主要用于 Web 应用,但也可以用于桌面应用程序间的实时通信。
7.2. 特点
实时通信:支持实时数据传输,如聊天应用、实时监控等。
简化的 API:提供高层次的 API,简化实时通信的实现。
跨平台:支持多种客户端,包括 .NET、JavaScript、Java 等。
7.3. 实现方式
7.3.1. 服务器端(Hub)
using Microsoft.AspNetCore.SignalR;public class ChatHub : Hub
{public async Task SendMessage(string user, string message){await Clients.All.SendAsync("ReceiveMessage", user, message);}
}
7.3.2. 配置服务器
Startup.cs
public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddSignalR();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapHub<ChatHub>("/chatHub");});}
}
7.3.3. 客户端(C#)
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){var connection = new HubConnectionBuilder().WithUrl("http://localhost:5000/chatHub").Build();connection.On<string, string>("ReceiveMessage", (user, message) =>{Console.WriteLine($"{user}: {message}");});await connection.StartAsync();Console.WriteLine("已连接到服务器。");while (true){string input = Console.ReadLine();if (input == "exit") break;await connection.InvokeAsync("SendMessage", "Client", input);}await connection.StopAsync();}
}
7.4. 使用场景
实时数据更新,如股票行情、实时监控系统。
聊天应用、多人游戏等需要即时交互的应用。
需要实时通知和推送的桌面或移动应用。
8. 共享数据库
8.1. 概述
通过使用一个共享的数据库,两个进程可以通过读写数据库中的数据来实现通信。这种方法简单且可靠,适用于不需要实时通信的场景。
8.2. 特点
简单实现:利用现有的数据库系统,无需额外的通信机制。
持久性:数据持久存储,适用于需要记录通信历史的应用。
跨平台支持:适用于不同操作系统和编程语言的进程。
8.3. 实现方式
8.3.1. 发送方写入数据
using System;
using System.Data.SqlClient;class DatabaseSender
{static void Main(string[] args){string connectionString = "Server=your_server;Database=your_db;User Id=your_user;Password=your_password;";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();string insertQuery = "INSERT INTO Messages (Sender, Content, Timestamp) VALUES (@sender, @content, @timestamp)";using (SqlCommand command = new SqlCommand(insertQuery, connection)){command.Parameters.AddWithValue("@sender", "SenderProcess");command.Parameters.AddWithValue("@content", "Hello from sender!");command.Parameters.AddWithValue("@timestamp", DateTime.Now);command.ExecuteNonQuery();Console.WriteLine("已发送消息到数据库。");}}}
}
8.3.2. 接收方读取数据
using System;
using System.Data.SqlClient;class DatabaseReceiver
{static void Main(string[] args){string connectionString = "Server=your_server;Database=your_db;User Id=your_user;Password=your_password;";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();string selectQuery = "SELECT Sender, Content, Timestamp FROM Messages ORDER BY Timestamp DESC";using (SqlCommand command = new SqlCommand(selectQuery, connection)){using (SqlDataReader reader = command.ExecuteReader()){while (reader.Read()){string sender = reader.GetString(0);string content = reader.GetString(1);DateTime timestamp = reader.GetDateTime(2);Console.WriteLine($"{timestamp} - {sender}: {content}");}}}}}
}
8.4. 使用场景
不需要实时通信但需要可靠数据交换的应用程序。
需要记录通信历史或数据持久性的场景。
多个进程或服务需要共享大量数据。
8.5. 注意事项
性能:数据库通信通常比内存共享或管道通信更慢,适合不频繁的数据交换。
并发控制:需要处理多进程对数据库的并发访问,确保数据一致性。
安全性:确保数据库连接的安全性,防止未经授权的访问。
9. Windows API(Windows Messages)
9.1. 概述
利用 Windows API 发送和接收消息也是一种 IPC 方式,特别适用于 GUI 应用程序之间的通信。
9.2. 特点
适用于 GUI 应用:主要用于具有窗口句柄的应用程序。
简单实现:适合发送简单命令或通知。
9.3. 实现方式
9.3.1. 发送消息(发送方)
using System;
using System.Runtime.InteropServices;class MessageSender
{// 引入 SendMessage 函数[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 引入 FindWindow 函数[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);static void Main(string[] args){// 获取目标窗口句柄,可以通过窗口标题查找IntPtr hWnd = FindWindow(null, "接收消息的窗口标题");if (hWnd != IntPtr.Zero){string message = "Hello from sender!";byte[] msgBytes = System.Text.Encoding.UTF8.GetBytes(message);IntPtr lParam = Marshal.AllocHGlobal(msgBytes.Length + 1);Marshal.Copy(msgBytes, 0, lParam, msgBytes.Length);Marshal.WriteByte(lParam, msgBytes.Length, 0); // 添加 null 终止符SendMessage(hWnd, WM_CUSTOM, IntPtr.Zero, lParam);Marshal.FreeHGlobal(lParam);Console.WriteLine("已发送消息。");}else{Console.WriteLine("未找到目标窗口。");}}
}
9.3.2. 接收消息(接收方)
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;class MessageReceiver : Form
{// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 重写 WndProc 方法以处理自定义消息protected override void WndProc(ref Message m){if (m.Msg == WM_CUSTOM){// 获取消息内容int length = 0;while (Marshal.ReadByte(m.LParam, length) != 0) length++;byte[] buffer = new byte[length];Marshal.Copy(m.LParam, buffer, 0, length);string receivedMessage = Encoding.UTF8.GetString(buffer);MessageBox.Show($"收到消息:{receivedMessage}");}base.WndProc(ref m);}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new MessageReceiver());}
}
9.4. 使用场景
简单的 GUI 应用程序之间的通信。
发送简单的命令或通知。
不需要高性能或大量数据传输的场景。
9.5. 注意事项
窗口句柄:需要获取目标窗口的句柄(Handle),可以通过窗口标题或类名查找。
消息格式:确保发送方和接收方对消息格式有一致的约定。
安全性:避免发送恶意消息,确保消息的合法性。
10. 其他 IPC 方法
10.1. COM(Component Object Model)
概述:COM 是微软的一种组件软件架构,用于不同进程或不同编程语言间的对象通信。
特点:跨语言、跨进程、支持对象导向。
使用场景:需要复杂对象交互和跨语言支持的场景。
缺点:配置复杂,学习曲线陡峭。
10.2. 共享数据库
概述:通过共享数据库(如 SQL Server, SQLite, MySQL)进行数据交换。
特点:数据持久化、易于管理、跨平台。
使用场景:不需要实时通信但需要可靠数据交换的场景。
缺点:性能较低,不适合高频率数据交换。
10.3. 文件系统
概述:通过在文件系统中读写文件来实现通信。
特点:实现简单、无需特殊配置。
使用场景:简单的数据交换,如配置文件、日志记录等。
缺点:不适合实时通信,性能较低,易受文件锁定影响。
11. 性能和安全性考虑
11.1. 性能优化
选择合适的 IPC 方法:根据通信需求(数据量、实时性、跨网络等)选择最合适的 IPC 方法。
减少数据传输量:只传输必要的数据,避免冗余传输。
使用高效的数据格式:如二进制格式代替文本格式,减少解析开销。
并发处理:利用异步编程和并发机制,提升数据处理效率。
11.2. 安全性
身份验证:确保只有授权的进程可以进行通信。
数据加密:在传输敏感数据时,使用加密机制保护数据安全。
访问控制:设置严格的访问权限,防止未授权的访问和操作。
防止注入攻击:验证和清理接收到的数据,防止恶意代码注入。
12. 总结
C# 提供了多种进程间通信(IPC)方法,涵盖了从简单的数据交换到复杂的实时通信需求。选择合适的 IPC 方法需要根据具体的应用场景、性能需求和安全要求来决定。以下是常见 IPC 方法的简要对比:
IPC 方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
命名管道 | 高效、支持双向通信、可跨网络 | 仅限于同一台机器或局域网 | 高效数据传输、双向通信 |
套接字(Sockets) | 灵活、支持多协议、跨平台 | 实现复杂、需要处理网络延迟和安全性 | 跨网络通信、实时应用如聊天和游戏 |
内存映射文件 | 高性能、适合共享大量数据 | 需要处理内存管理和同步问题 | 实时数据共享、大量数据交换 |
信号和消息 | 简单、适用于 GUI 应用 | 仅适用于具有窗口句柄的应用,有限的数据传输能力 | 简单命令或通知的 GUI 应用通信 |
WCF | 多协议支持、高度可配置、安全性强 | 配置复杂、学习曲线陡峭 | 复杂服务通信、跨平台和跨语言应用 |
SignalR | 实时通信、简化的 API、跨平台 | 主要用于 Web 应用,桌面应用需要额外配置 | 实时数据更新、聊天应用、实时监控系统 |
共享数据库 | 数据持久化、易于管理、跨平台 | 性能较低、不适合高频率实时通信 | 可靠的数据交换、需要记录通信历史的场景 |
文件系统 | 实现简单、无需特殊配置 | 不适合实时通信、性能低、易受文件锁定影响 | 简单的数据交换、配置文件和日志记录 |
COM | 跨语言、支持复杂对象交互 | 配置复杂、学习曲线陡峭 | 需要复杂对象交互和跨语言支持的场景 |
相关文章:
C# 两个进程/exe通讯方式 两个应用程序通讯方式
C# 两个exe通讯方式 两个应用程序通讯方式 1. 命名管道(Named Pipes) 1.1. 概述 命名管道是一种用于在同一台机器或网络中不同进程之间进行双向通信的机制。它支持同步和异步通信,适用于需要高效数据传输的场景。 1.2. 特点 双向通信&am…...

ubuntu下打开摄像头
ubuntu下打开摄像头 在Ubuntu下,你可以使用cheese,这是一个开源的摄像头应用程序。如果你还没有安装它,可以通过以下命令安装: sudo apt-get updatesudo apt-get install cheese 安装完成后,你可以通过命令行启动它: cheese 或者,你也可以使用ffmpeg来打开摄像头并进…...

ABAP 表转JSON格式
FUNCTION ZRFC_FI_SEND_PAYPLAN2BPM. *"---------------------------------------------------------------------- *"*"本地接口: *" IMPORTING *" VALUE(INPUT) TYPE ZSRFC_FI_SEND_PAYBPM_IN *" EXPORTING *" VAL…...

oceanbase的日志量太大,撑爆磁盘,修改下日志级别
oceanbase的日志量太大,撑爆磁盘,修改下日志级别: [adminlnpg ~]$ obclient -h127.0.0.1 -uroot -P2881 -plinux123 Welcome to the OceanBase. Commands end with ; or \g. Your OceanBase connection id is 3221561020 Server version: O…...
【C++11】lambda表达式
前言: 随着 C11 的发布,C 标准引入了许多新特性,使语言更加现代化,开发者编写的代码也变得更加简洁和易于维护。Lambda 表达式是其中一个重要的特性,它提供了一种方便的方式来定义匿名函数,这在函数式编程范…...

前端学习-css的背景(十六)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 背景颜色 语法格式 背景图片 语法格式 背景平铺 语法格式 背景图片位置 语法格式 参数代表的意思 参数是方位名词 参数是精确单位 参数是混合单位 背…...

使用Postman搞定各种接口token实战
现在许多项目都使用jwt来实现用户登录和数据权限,校验过用户的用户名和密码后,会向用户响应一段经过加密的token,在这段token中可能储存了数据权限等,在后期的访问中,需要携带这段token,后台解析这段token才…...

ssh连接慢的问题或远程连接服务超时
问题原因: 在SSH登录过程中,服务器会通过反向DNS查找客户端的主机名,然后与登录的IP地址进行匹配,以验证登录的合法性。如果客户端的IP没有域名或DNS服务器响应缓慢,这可能导致SSH登录过慢。为了解决这个问题…...

基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet模型【pytorch框架+python源码】
更多目标检测和图像分类识别项目可看我主页其他文章 功能演示: 基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet【pytorch框架,python,tkinter】_哔哩哔哩_bilibili (一)简介 基于卷积神…...

数据结构与算法:栈与队列的高级应用
目录 3.1 栈的高级用法 3.2 队列的深度应用 3.3 栈与队列的综合应用 总结 数据结构与算法:栈与队列的高级应用 栈和队列是两种重要的线性数据结构,它们在计算机科学和工程的许多领域都有广泛的应用。从函数调用到表达式求值,再到任务调度…...
macos php开发环境之macport安装的php扩展安装,php常用扩展安装,port中可用的所有php扩展列表
macos中,我们使用了port 安装了php后,默认只带有php基本的核心扩展的, 如果需要使用其他的扩展,如 redis, https, xdebug等扩展就需要我们手动来安装对应的扩展。 macos php开发环境 macport安装的php的方法见macos 中…...

使用Pytorch+Numpy+Matplotlib实现手写字体分类和图像显示
文章目录 1.引用2.内置图片数据集加载3.处理为batch类型4.设置运行设备5.查看数据6.绘图查看数据图片(1)不显示图片标签(2)打印图片标签(3)图片显示标签 7.定义卷积函数8.卷积实例化、损失函数、优化器9.训练和测试损失、正确率(1)训练(2)测试(3)循环(4)损失和正确率曲线(5)输出…...
kimi帮我解决ubuntu下软链接文件夹权限不够的问题
我的操作如下 ubuntuubuntu-QiTianM420-N000:~$ ln -s /media/ubuntu/4701aea3-f883-40a9-b12f-61e832117414 code ubuntuubuntu-QiTianM420-N000:~$ ls -l 总用量 636 drwxrwxr-x 2 ubuntu ubuntu 4096 5月 7 17:16 bin drwxrwxrwx 2 ubuntu ubuntu 4096 5月 8 13…...

如何去除背景音乐保留人声?保留人声,消除杂音
在日常生活和工作中,我们经常遇到需要处理音频的情况,尤其是当我们想要去除背景音乐,仅保留人声时。这种需求在处理电影片段、制作音乐MV、或者提取演讲内容等场景中尤为常见。本文将为您详细介绍如何去除背景音乐并保留人声,帮助…...
2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数
2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数 2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数 文章目录 2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数KfRaiseIrql 函数 KfRaiseIrql 函数 /*********************************************************************** NAME …...

【新书】使用 OpenAI API 构建 AI 应用:利用 ChatGPT等构建 10 个 AI 项目(第二版),404页pdf
通过构建 ChatGPT 克隆、代码错误修复器、测验生成器、翻译应用、自动回复邮件生成器、PowerPoint 生成器等项目,提升您的应用开发技能。 关键特性 通过掌握 ChatGPT 概念(包括微调和集成),转变为 AI 开发专家 通过涵盖广泛 AI …...
修改PostgreSQL表中的字段排列顺序
二、通过修改系统表(pg_attribute)达到字段重新排序的目的有关系统表的概述及用途可以查看官网:http://www.pgsqldb.org/pgsqldoc-cvs/catalogs.html 表名字表用途pg_class表,索引,序列,视图(”关系”)pg_…...

canvas实现手写功能
1.从接口获取手写内容,处理成由单个字组成的数组(包括符号) 2.合成所有图的时候,会闪现outputCanvas合成的图,注意隐藏 3.可以进行多个手写内容切换 4.基于uniapp的 <template><view class"content&quo…...
Python知识点:基于Python技术,如何使用TensorFlow进行目标检测
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 使用TensorFlow进行目标检测的完整指南 目标检测是计算机视觉领域中的一项重要任…...

初始爬虫13(js逆向)
为了解决网页端的动态加载,加密设置等,所以需要js逆向操作。 JavaScript逆向可以分为三大部分:寻找入口,调试分析和模拟执行。 1.chrome在爬虫中的作用 1.1preserve log的使用 默认情况下,页面发生跳转之后…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...