목차
프로세스간 통신 방법(IPC - Ineter Process Communication)
프로세스 간 통신은 서로 다른 프로세스가 데이터를 주고받기 위한 메커니즘입니다.
프로세스간 통신방법의 종류
1. 파이프
•
개념 : 파이프는 한 프로세스의 출력을 다른 프로세스의 입력으로 직접 연결하는 통신 메커니즘입니다.
•
유형 :
◦
익명 파이프 : 주로 부모 프로세스와 자식 프로세스 간의 통신에 사용됩니다. 메모리를 공유하는 프로세스 간에만 사용할 수 있으며, 단방향 통신을 제공합니다.
◦
네임드 파이프 : 네트워크를 통한 두 프로세스 간의 통신이 가능하며, 양방향 통신을 지원합니다.
네임드 파이프 예시
using System;
using System.IO.Pipes;
class NamedPipeServer
{
static void Main(string[] args)
{
using (var pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.Out))
{
Console.WriteLine("Named Pipe Server waiting for connection...");
pipeServer.WaitForConnection();
using (var writer = new StreamWriter(pipeServer))
{
writer.AutoFlush = true;
writer.WriteLine("Hello, Named Pipe Client!");
}
}
}
}
C#
복사
using System;
using System.IO.Pipes;
class NamedPipeClient
{
static void Main(string[] args)
{
using (var pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.In))
{
pipeClient.Connect();
Console.WriteLine("Connected to Named Pipe Server.");
using (var reader = new StreamReader(pipeClient))
{
string message = reader.ReadLine();
Console.WriteLine("Received from server: " + message);
}
}
}
}
C#
복사
익명 파이프 예시
using System;
using System.Diagnostics;
using System.IO;
class AnonymousPipeServer
{
static void Main()
{
using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
{
Console.WriteLine("[Server] Pipe handle: " + pipeServer.GetClientHandleAsString());
ProcessStartInfo psi = new ProcessStartInfo()
{
FileName = "dotnet", // Or the path to the executable of the child process
Arguments = $"run --project ./PathToChildProject {pipeServer.GetClientHandleAsString()}", // Pass the client handle to the child process as an argument
UseShellExecute = false
};
Process childProcess = Process.Start(psi);
// We don't need the client handle anymore.
pipeServer.DisposeLocalCopyOfClientHandle();
try
{
// Send a message to the child process.
using (StreamWriter sw = new StreamWriter(pipeServer))
{
sw.AutoFlush = true;
sw.WriteLine("Hello, child process!");
}
}
catch (IOException e)
{
Console.WriteLine("Error: " + e.Message);
}
childProcess.WaitForExit();
childProcess.Close();
Console.WriteLine("[Server] Child process exited.");
}
}
}
C#
복사
using System;
using System.IO;
using System.IO.Pipes;
class AnonymousPipeClient
{
static void Main(string[] args)
{
if (args.Length > 0)
{
using (PipeStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, args[0]))
{
Console.WriteLine("[Client] Reading from pipe...");
using (StreamReader sr = new StreamReader(pipeClient))
{
string temp;
// Read the server's message.
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("[Client] Received from server: " + temp);
}
}
}
}
}
}
C#
복사
2. 공유 메모리
•
개념 : 공유 메모리는 두 개 이상의 프로세스가 접근할 수 있는 메모리 영역입니다.
•
구현: 프로세스는 공유 메모리 영역을 생성하거나 기존 영역에 접근하기 위해 운영 체제의 API를 사용합니다.
공유 메모리 예시
using System;
using System.IO.MemoryMappedFiles;
class SharedMemoryExample
{
static void Main()
{
string mapName = "sharedMemoryExample";
int capacity = 1024; // 바이트 단위
// 메모리 맵 파일 생성
using (var mmf = MemoryMappedFile.CreateOrOpen(mapName, capacity))
{
// 메모리에 쓰기
using (var accessor = mmf.CreateViewAccessor())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, Shared Memory!");
accessor.WriteArray(0, data, 0, data.Length);
}
Console.WriteLine("Data written to shared memory.");
// 메모리에서 읽기
using (var accessor = mmf.CreateViewAccessor())
{
byte[] data = new byte[capacity];
accessor.ReadArray(0, data, 0, data.Length);
string message = System.Text.Encoding.UTF8.GetString(data).TrimEnd('\0');
Console.WriteLine("Data read from shared memory: " + message);
}
}
}
}
C#
복사
3. 소켓 통신
•
개념 : 소켓은 네트워크를 통해 서로 다른 시스템에 있는 프로세스 간의 양방향 통신을 가능하게 합니다.
•
구현 : .NET 프레임워크에서는 System.Net.Sockets 네임스페이스를 통해 소켓 통신을 구현할 수 있습니다.
소켓 통신은 말 그대로 네트워크를 통한 통신 방법이기 때문에 이 부분의 예시는 생략하도록 하겠습니다.
4. 메시지 큐
•
개념 : 메시지 큐는 메시지의 목록을 저장하는데, 한 프로세스가 메시지를 큐에 전송하고 다른 프로세스가 이를 받아 처리합니다.
•
구현: 메시지 큐는 통신할 데이터를 메시지로 패키징하여 큐에 넣는 방식으로 작동합니다. 프로세스는 메시지 큐 시스템을 통해 메시지를 보내고 받습니다.
메시지 큐 예시
using System;
using System.Messaging;
class MessageQueueExample
{
static void Main()
{
string queuePath = @".\Private$\TestQueue";
// 큐 생성
if (!MessageQueue.Exists(queuePath))
{
MessageQueue.Create(queuePath);
}
// 메시지 보내기
using (var mq = new MessageQueue(queuePath))
{
mq.Send("Hello, Message Queue!");
Console.WriteLine("Message sent.");
}
// 메시지 받기
using (var mq = new MessageQueue(queuePath))
{
var message = mq.Receive();
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
Console.WriteLine("Received message: " + message.Body);
}
}
}
C#
복사