본문 바로가기
프로그래밍/C Sharp

[ C# ] 프로그램간 통신 ( IPC 이용 )

by jeong-f 2021. 11. 10.
반응형

IPC는 Inter Process Communication의 약자로 커널 영역에서 제공하는 내부 프로세스 간 통신을 이용해서

그 기능을 구현할 수 있으며, 이를 이용하여 애플리케이션 간에 통신을 구현할 수 있습니다.

IPC의 종류에는 PIPE, Named PIPE, Message Queue, Shared Memory, Memory Map, socket 등이 있지만

여기서 다루는 Shared Memory 방식은 동일한 클래스를 참조함으로써 별도의 통신 구성 명령을 만들 필요 없이 변수 간의 데이터 교류가 이루어져 더욱 편리한 코드 작성이 가능하게 해 줍니다.

공용 DLL 생성

일반적인 샘플에서는 서버 생성 및 연결코드를 각각의 프로그램에 넣어서 사용하나 소스 관리의 편의를 위하여 dll파일 안에 초기 연결 부분을 추가하였습니다.

현재 IPC 연결방식으로 구현되었고, 필요에 따라  TCP,  Http 방식으로 수정해서 사용하셔도 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
 
namespace RemoteObjects
{
    public class RemoteObject : MarshalByRefObject
    {
        static int count = 0;
        static string str = "";
 
        public int Count
        {
            get { return RemoteObject.count; }
            set { RemoteObject.count = value; }
        }
        public string Str
        {
            get { return RemoteObject.str; }
            set { RemoteObject.str = value; }
        }
 
        public static void CreateServer()
        {
            try
            {
                IpcServerChannel svr = new IpcServerChannel("remote"); //remote 포트 만들기
                ChannelServices.RegisterChannel(svr, false); // 채널 등록
                RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject), "test", WellKnownObjectMode.SingleCall); // 원격 객체 준비작업
 
                Console.WriteLine("서버 시작 " + svr.GetChannelUri());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        public static void CreateClient()
        {
            IpcClientChannel clientChannel = new IpcClientChannel(); 
 
//클라이언트  생성
            ChannelServices.RegisterChannel(clientChannel, false);
            RemotingConfiguration.RegisterWellKnownClientType(typeof(RemoteObject), "ipc://remote/test");
        }
    }
}
cs

 

서버

서버에는 str = 입력받은 값 , count= 증가 수를 한번 입력될 때마다 전송합니다. Q명령이 들어오면 종료합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using RemoteObjects;
 
namespace RemoteServer
{
    class Program
    {
        [STAThread]
        [SecurityPermission(SecurityAction.Demand)]
        static void Main(string[] args)
        {
            RemoteObject.CreateServer();
            RemoteObject ro = new RemoteObject();
 
            int nCount = 0;
            ro.Count = nCount;
 
            while (true)
            {
                Console.Write("아무키나 눌러주세요 , Q=종료");
                string tx = Console.ReadLine();
 
                if (tx.ToUpper() == "Q")
                {
                    break;
                }
 
                nCount++;
                ro.Count = nCount;
                ro.Str = tx;
 
                Console.WriteLine("카운터={0}",nCount);
            }
        }
    }
}
cs

 

클라이언트

반응형

클라이언트에서는 count가 변화될 때마다 표시하고 str 이 Q 일 경우 종료하고 다른 명령이 들어올 경우 표시합니다.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using RemoteObjects;
namespace RemoteClient
{
    class Program
    {
        [STAThread]
        [SecurityPermission(SecurityAction.Demand)]
        static void Main(string[] args)
        {
            RemoteObject.CreateServer();
            RemoteObject ro = new RemoteObject();
            int nCount = 0;// IPC와 비교를 위한 숫자 변수 
            string sStr = "";// IPC와 비교를 위한 문자 변수
            while (true)
            {
                if (nCount != ro.nCount)
                {
                    nCount = ro.nCount;
                    sStr = ro.sStr;
                    Console.WriteLine("{0}", nCount);
                    Console.WriteLine("서버입력={0}", sStr);
                }
            }
        }
    }
}
 
cs

 

실행 결과

서버에서 문자를 입력할 때마다 1씩 카운터를 증가하고, 입력된 문자를 ipc에 올려 클라이언트에서 표시되는 것을 확인할 수 있었습니다.

예상 문제점

사용 중 "System.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: Access is denied" 에러가 발생할 경우 권한 오류로 인하여 발생하는 것으로 다음 사이트의 내용을 참고하여 수정하시기 바랍니다.

 

.NET Remoting In Windows Service

Hi, My windows service application contains an IpcChannel which listens msg from client. If I install it with MyServiceProcessInstaller.Account="LocalSystem" or "LocalService", or "NetworkService". Then I got an exception "System.Runtime.Remoting.RemotingE

social.msdn.microsoft.com

반응형

댓글