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

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. 命名管道&#xff08;Named Pipes&#xff09; 1.1. 概述 命名管道是一种用于在同一台机器或网络中不同进程之间进行双向通信的机制。它支持同步和异步通信&#xff0c;适用于需要高效数据传输的场景。 1.2. 特点 双向通信&am…...

ubuntu下打开摄像头

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

ABAP 表转JSON格式

FUNCTION ZRFC_FI_SEND_PAYPLAN2BPM. *"---------------------------------------------------------------------- *"*"本地接口&#xff1a; *" IMPORTING *" VALUE(INPUT) TYPE ZSRFC_FI_SEND_PAYBPM_IN *" EXPORTING *" VAL…...

oceanbase的日志量太大,撑爆磁盘,修改下日志级别

oceanbase的日志量太大&#xff0c;撑爆磁盘&#xff0c;修改下日志级别&#xff1a; [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表达式

前言&#xff1a; 随着 C11 的发布&#xff0c;C 标准引入了许多新特性&#xff0c;使语言更加现代化&#xff0c;开发者编写的代码也变得更加简洁和易于维护。Lambda 表达式是其中一个重要的特性&#xff0c;它提供了一种方便的方式来定义匿名函数&#xff0c;这在函数式编程范…...

前端学习-css的背景(十六)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 背景颜色 语法格式 背景图片 语法格式 背景平铺 语法格式 背景图片位置 语法格式 参数代表的意思 参数是方位名词 参数是精确单位 参数是混合单位 背…...

使用Postman搞定各种接口token实战

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

ssh连接慢的问题或远程连接服务超时

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

基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet模型【pytorch框架+python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于卷积神经网络的蔬菜识别系统&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python&#xff0c;tkinter】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积神…...

数据结构与算法:栈与队列的高级应用

目录 3.1 栈的高级用法 3.2 队列的深度应用 3.3 栈与队列的综合应用 总结 数据结构与算法&#xff1a;栈与队列的高级应用 栈和队列是两种重要的线性数据结构&#xff0c;它们在计算机科学和工程的许多领域都有广泛的应用。从函数调用到表达式求值&#xff0c;再到任务调度…...

macos php开发环境之macport安装的php扩展安装,php常用扩展安装,port中可用的所有php扩展列表

macos中&#xff0c;我们使用了port 安装了php后&#xff0c;默认只带有php基本的核心扩展的&#xff0c; 如果需要使用其他的扩展&#xff0c;如 redis, https&#xff0c; 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…...

如何去除背景音乐保留人声?保留人声,消除杂音

在日常生活和工作中&#xff0c;我们经常遇到需要处理音频的情况&#xff0c;尤其是当我们想要去除背景音乐&#xff0c;仅保留人声时。这种需求在处理电影片段、制作音乐MV、或者提取演讲内容等场景中尤为常见。本文将为您详细介绍如何去除背景音乐并保留人声&#xff0c;帮助…...

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 生成器等项目&#xff0c;提升您的应用开发技能。 关键特性 通过掌握 ChatGPT 概念&#xff08;包括微调和集成&#xff09;&#xff0c;转变为 AI 开发专家 通过涵盖广泛 AI …...

修改PostgreSQL表中的字段排列顺序

二、通过修改系统表(pg_attribute)达到字段重新排序的目的有关系统表的概述及用途可以查看官网&#xff1a;http://www.pgsqldb.org/pgsqldoc-cvs/catalogs.html 表名字表用途pg_class表&#xff0c;索引&#xff0c;序列&#xff0c;视图&#xff08;”关系”&#xff09;pg_…...

canvas实现手写功能

1.从接口获取手写内容&#xff0c;处理成由单个字组成的数组&#xff08;包括符号&#xff09; 2.合成所有图的时候&#xff0c;会闪现outputCanvas合成的图&#xff0c;注意隐藏 3.可以进行多个手写内容切换 4.基于uniapp的 <template><view class"content&quo…...

Python知识点:基于Python技术,如何使用TensorFlow进行目标检测

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 使用TensorFlow进行目标检测的完整指南 目标检测是计算机视觉领域中的一项重要任…...

初始爬虫13(js逆向)

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

前端发送了请求头的参数,经debug发现后端请求对象请求头中没有该参数

debug测试&#xff0c;发现前端发来请求头中确实没有找到添加的请求头参数&#xff0c;但是 Network 中却显示请求头中有该参数信息。 原因是RequestHeaders中设置的请求参数含有下划线&#xff0c;NGINX将静默地丢弃带有下划线的HTTP标头&#xff0c;这样做是为了防止在将头映…...

雷池社区版如何使用静态资源的方式建立站点

介绍&#xff1a; SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、X…...

车载电源OBC+DC/DC

文章目录 1. 车载DC/DC应用场景2. PFC2.1 简介2.2 专业名词2.3 常见拓扑结构2.3.1 传统桥式PFC2.3.2 普通无桥型PFC2.3.3 双Boost无桥PFC2.3.4 图腾柱PFC2.3.5 参考资料 2.4 功率因数2.4.1 简介2.4.2 计算 3. DC/DC3.1 Boost升压电路3.1.1 简介3.1.2 电路框图3.1.3 工作原理3.1…...

【朝花夕拾】免费个人网页搭建:免费托管、CDN加速、个人域名、现代化网页模板一网打尽

现代化网页设计的免费宝藏&#xff1a;GitHub PagesCodePenCloudflareUS.KG 前言 在当今数字化时代&#xff0c;个人和企业越来越重视在线形象的建立。GitHub Pages 提供了一个免费且便捷的平台&#xff0c;允许用户托管静态网站。然而&#xff0c;GitHub Pages 默认的域名可…...

Spring Boot知识管理系统:用户体验设计

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…...

《数字信号处理》学习08-围线积分法(留数法)计算z 逆变换

目录 一&#xff0c;z逆变换相关概念 二&#xff0c;留数定理相关概念 三&#xff0c;习题 一&#xff0c;z逆变换相关概念 接下来开始学习z变换的反变换-z逆变换&#xff08;z反变化&#xff09;。 由象函数 求它的原序列 的过程就称为 逆变换。即 。 求z逆变换…...

vue3中的computed属性

模板界面&#xff1a; <template><div class"person"><h2>姓&#xff1a; <input type"text" v-model"person.firstName" /></h2><h2>名&#xff1a; <input type"text" v-model"person…...

C++学习笔记之vector容器

天上月&#xff0c;人间月&#xff0c;负笈求学肩上月&#xff0c;登高凭栏眼中月&#xff0c;竹篮打水碎又圆。 山间风&#xff0c;水边风&#xff0c;御剑远游脚下风&#xff0c;圣贤书斋翻书风&#xff0c;风吹浮萍又相逢。 STL(Standard Template Library,标准模板库 ) 从…...

LeNet-5(论文复现)

LeNet-5&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 LeNet-5&#xff08;论文复现&#xff09;概述LeNet-5网络架构介绍训练过程测试过程使用方式说明 概述 LeNet是最早的卷积神经网络之一。1998年&#xff0c;Yann LeCun第一次将LeN…...

基于SpringBoot+Vue+Uniapp汽车保养系统小程序的设计与实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而…...