c# 인터프로세스 통신 – named pipe
프로세스들 사이에서 대이터를 주고 받아야 할 때가 있다.
예를 들어 이런 경우에 쓸모 있다. ls증권의 api를 이용한 애플리캐이션은 32 비트로만 빌드를 할 수 있다. 32 비트 애플리캐이션은 메모리를 원칙적으로 2gb까지 이용할 수 있으며 변칙적으로 4gb까지도 가능하다. 사실적으로는 3gb 정도까지 쓸 수 있다. 이는 커다란 제약이다.
위의 api로 32 비트 서버 애플리캐이션을 만들고 64 비트 클라이언트 애플리캐이션을 만들어 쓰면 위의 문제를 피할 수 있다. 서버는 ls증권으로부터 대이터를 받아 클라이언트로 보내는 거까지만 하는 거다. 아래의 예제를 응용하면 된다.
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
NamedPipeServerStream NamedPipeServerStream1;
private void Form1_Load(object sender, EventArgs e)
{
NamedPipeServerStream1 = new("TestPipe");
NamedPipeServerStream1.WaitForConnection();
Text = "connected";
}
private void Form1_Click(object sender, EventArgs e)
{
string message = "test";
byte[] buffer = Encoding.UTF8.GetBytes(message);
NamedPipeServerStream1.Write(buffer, 0, buffer.Length);
}
}
}
using System.IO.Pipes;
using System.Text;
namespace WinFormsApp2
{
public partial class Form1 : Form
{
NamedPipeClientStream NamedPipeClientStream1;
private void Form1_Load(object sender, EventArgs e)
{
NamedPipeClientStream1 = new("TestPipe");
NamedPipeClientStream1.Connect();
byte[] buffer = new byte[256];
PipeReadState pipeReadState = new();
pipeReadState.NamedPipeClientStream = NamedPipeClientStream1;
pipeReadState.Buffer = buffer;
NamedPipeClientStream1.BeginRead(buffer, 0, buffer.Length, ReadCallBack, pipeReadState);
}
class PipeReadState
{
public NamedPipeClientStream NamedPipeClientStream;
public byte[] Buffer;
}
void ReadCallBack(IAsyncResult asyncResult)
{
PipeReadState pipeReadState = (PipeReadState)asyncResult.AsyncState;
int length = pipeReadState.NamedPipeClientStream.EndRead(asyncResult);
string message = Encoding.UTF8.GetString(pipeReadState.Buffer, 0, length);
BeginInvoke(invoke);
void invoke()
{
Text = message;
}
}
}
}
프로세스들 사이의 통신은 pipe라는 걸 이용한다. 파이프에는 이름이 있는named 것과 없는anonymous 게 있는데 익명 파이프는 부모 자식 프로세스들 사이에서 통신할 때 이용하는 거라 위의 사례에는 쓸 수 없다.
가능한 간단하게 만든 예제라 WaitForConnection은 동기로 작동하게 뒀다. 실제로 쓸 때에는 await로 해야 한다.
콜백은 새로 만들어지는 뜨레드에서 처리되므로 매인 뜨레드에서 작동하는 유저 인터패이스를 수정할 수 없다. 그래서 BeginInvoke를 썼다.