C# 멀티 서버와 통신하는 클라이언트 소켓통신 프로그램 개발방법에 대해 문의드립니다.

C# 멀티 서버와 통신하는 클라이언트 소켓통신 프로그램(COSMOS)을
Windows Service 프로그램으로 개발하고자 합니다.

캡처

시스템 구성은 위와 같으며 요구사항은 아래와 같습니다.

  1. 계측기(Server)는 20개 정도임
  2. 각각의 계측기(Server)에 Client (COSMOS)가 주기적(10분)으로 접속, 데이터를 요청 후
    받아서 DB에 저장
  3. 각각의 계측기(Server)에 특별한 이벤트가 발생했는지를 확인하기 위해
    Client (COSMOS)가 주기적(15초)으로 각각의 Server에 접속, 데이터를 요청하여
    받은 데이터에서 이벤트가 발생한 것으로 파악되면 Server에 이벤트 내용을
    요청하여 받아서 DB에 저장
  4. 사용자가 실시간 Web 모니터링 화면에 접속한 경우 Client 프로그램 (COSMOS)은
    주기적(1초)으로 계측기(Server)에 데이터를 요청 후, 받아서 Web화면으로 전달하고
    사용자가 다른 화면으로 이동하면 Connection 종료

C#을 이용하여 싱글 Server와 통신하는 Client 프로그램을
Windows Service 프로그램으로 개발해본 적이 있으나
위와 같은 형태의 멀티 Server와 통신하는 Client 프로그램은 개발해 본 적이 없고
인터넷에서 찾기도 어렵네요.

그리고 Socket Program (COSMOS)은 계측기(Server)와 통신하기 위해서는 Client 기능이 필요하고
Web 화면과 통신(Web Socket??)을 위해서는 Server 기능이 필요할 것 같은데
맞는지요?

어떻게 방향을 잡아야 할지요…
유사 샘플 소스가 있다면 많은 도움이 될 것 같습니다.

선배 고수님들의 애정어린 조언을 부탁드립니다.

감사합니다.

2 Likes
  1. 주기적으로 접속이란 의미는 (접속 → 요청 → 접속 끊음) 의 의미인가요?
    • 그렇다면 1초 주기적 접속은 1초마다 접속/접속 끊음이 발생하나요?
  2. COSMOS → 사용자 웹 화면의 실시간 데이터 제공은 폴링을 하거나 웹소켓(또는 좀 더 사용하기 편리한 SignalR 등)을 이용해 제공하거나 좀 더 사용하기 편리한 Blazor Server를 이용하는 방법이 있습니다. Blazor Server를 사용할 경우 세션 연결된 서버 랜더링을 사용하므로 값이 변경될 때 웹 화면에 실시간으로 값을 변경할 수 있습니다.
  3. ASP.NET Core의 호스트 서비스를 백그라운드로 구동해서 특정 시간 마다 서버에 접속해서 처리하는 방식이 있습니다. 또는 Quartz등의 스케줄러를 이용하는 방법도 있습니다.
  4. 각각의 서버를 하나의 클라이언트에서 처리하지 마시고 서버당 클라이언트를 건건이 백그라운드 서비스로 돌릴 수 있습니다.
2 Likes

답변 감사드립니다.

  1. 사용자가 실시간 모니터링 화면에 접속했을 경우에는
    COSMOS가 Server에 접속하여 1초마다 데이터를 요청하여 Web화면에
    보내다가 사용자가 다른 화면으로 이동할 경우 Server와의 Connection을
    종료하는 형태로 개발해야 할 것 같습니다.

답변해주신 내용 중에서
각각의 서버를 하나의 클라이언트에서 처리하지 않고
서버당 클라이언트를 건건이 백그라운드 서비스로 돌린다는 것은
어떤 형태인지 구체적으로 알 수 있을까요?

1 Like

실시간 모니터링 기능을 구현하고자 하신다면 디모이님이 말씀하신 SignalR도입을 검토하시는게 좋을거 같습니다.
그리고 [Server에 Client (COSMOS)가 주기적(10분)으로 접속, 데이터를 요청 후 받아서 DB에 저장] 하는것보단 Server에 특별한 이벤트가 발생시 로깅용 DB 테이블에 이벤트 데이터를 입력하도록 개발하고, 개발하고자 하는 프로그램은SqlDependency로 로깅 테이블을 감시하다가 변동 내역을 처리하는 방식으로 개발한다면, 현재 구상안에선 주기적으로 발생할 소켓 프로그램과 서버의 통신 비용을 아낄 수 있습니다.
https://learn.microsoft.com/ko-kr/dotnet/framework/data/adonet/sql/detecting-changes-with-sqldependency

1 Like

정리하자면

  1. 서버는 이벤트 발생시 디비에 로깅
  2. 프로그램은 디비 테이블만 관제하고 있다가 이벤트 발생시 웹에 전달

이렇게 되겠네요.

1 Like

Server에서 받은 데이터를 DB에 저장하는 것은
시간별 데이터 변화에 대한 추이 등을 그래프로 표시해야 하기 때문입니다.

이벤트 발생에 대한 부분도 DB에 저장하는데 이는 이벤트 발생시
해당 데이터를 관리하기 위해서 입니다.

답변 감사드립니다.

1 Like

맞습니다.

그런데, 질문의 문맥이 일반적인 설계와 약간 다른 점이 있는 것 같습니다.
보통은 역으로 생각하는 것이 일반적입니다.

질문에서 Server 라고 표시해 놓은 것들은 (API)클라이언트가 되고, SocketProgram 은 (API)서버가 되는 것이죠.

이렇게 하면, 클라이언트들은 DB 에 저장해야 하는 것들을 스스로 결정하여, API 서버에 전송하고, API 서버는 이를 기계적으로 DB에 저장하는 식입니다.

이때 클라이언트의 지위는 데이터 공급자로 볼 수 있습니다.

Provider1, …, ProviderN => API Server => DB

API를 Restful Web Api 로 구성하면, Http message를 보낼 수 있는 한, 클라이언트는 어떤 프로그램이든지 상관이 없습니다.

서버는 데이터에 타임스탬프를 추가하여 DB에 저장하면 언제 저장된 것인지 나중에 확인할 수 있습니다.

질문은 다른 하나의 흐름도 요구하고 있는데, 그것은 데이터 저장소에서 데이터 소비자 - 일반적으로 데이터를 화면에 뿌려주는 클라이언트로의 흐름이 있습니다.

Consumer1, …, ConsumerN <= API Server <= DB

데이터 소비자는 데스크탑앱, 모바일 앱, 프론트엔드 앱, 다른 웹서버, 브라우저일 수도 있습니다.

브라우저일 경우, 서버는 데이터가 아니라, 화면(html)을 전송할 수 있습니다.

Browser1, … , BrowserN <= Rendering - Server <= DB

이러한 기능을 구현하기 위해 닷넷 기술을 사용한다면, 서버로 Asp.Net Core 프레임워크를 채택하는 게 보통입니다.

2 Likes

Server로 표현된 것들은 계측기로 Server Socket으로 개발되어서
COSMOS는 Client로 개발해야 하는 상황입니다.

답변 감사드립니다.

2 Likes

아마도 계측기 장비가 서버역할만 지원하나보네요. 아주 예전에 온도측정장비가 딱 비슷한 경우였는데 (메뉴얼에는 클라이언트 지원한다고 되어있었지만 안됨) 여튼 장비가 12개 정도 되었고 간단하게 PC에서 접속프로그램을 만들어 각 장비에 요청코드를 엄청 날렸습니다. (DDos의심으로 wifi가 패킷을 차단해버림 ㅋ) 그때는 PC어플로 만들어 실시간으로 데이터를 볼 수 있었는데 … 웹이라… 여튼 하나의 연결구성으론 다대일 연결시 서버측 응답에 따른 딜레이 및 여러변수로 상당히 애를 먹었던걸로 기억합니다. 그래서 결국에는 일대일로 전부다 구성을 했습니다. 그리고 장비이상이나 혹은 기타 이상으로 장비(서버)측에서 단절이 일어나면 제쪽에선 연결상태를 바로 알방법이 없었습니다. (실력이 모자란것도 한몫) 해서 일정시간 이상 응답이 없는 경우 그냥 연결을 끊고 다시 접속시도를 했는데 접속시도 몇 차례해서 복구가 안되면 담당자가 장비를 확인하게끔 메세지를 띄웠던걸로 기억하네요. 클라이언트구성에 참고가 되셨으면 좋겠습니다~!

2 Likes

일대일로 전부 구성하셨다는 것이
클라이언트 프로그램을 장비(서버)의 갯수만큼 실행하셨었다는
말씀인지요?

1 Like

아니요. 프로그램은 하나이고 송수신부를 1:1구성하도록 했습니다. 즉 연결개체가 20개면 수신부도 20개로 구성했었고 그냥 1:1로 각개통신하도록 구성했다고 보시면 될것 같습니다.

2 Likes

우선 BigSquare님이 말씀하신대로 일반적으로 사용하는 용어와 차이가 있어 보입니다.저도 앞으로의 설명에서 BigSquare님 처럼 계측기(클라이언트) Socket(서버)로 말씀드리겠습니다.

3.각각의 계측기(클라이언트)에 특별한 이벤트가 발생했는지를 확인하기 위해
COSMOS(서버)가 주기적(15초)으로 각각의 클라이언트에 접속

RE: 이 방식은 보통 폴링(polling)방식으로 불리는데 서버와 클라이언트 간에
빈번한 요청과 응답 (지금 같은경우엔 15초)으로 인해 자원을 비효율적으로 사용하고 부하를 증가시킬 수 있다는 단점이 있어 지양되는 방식입니다.

데이터를 요청하여 받은 데이터에서 이벤트가 발생한 것으로 파악되면 Server에 이벤트 내용을 DB에 저장

RE: 서버에서 데이터를 받아 이벤트 여부를 확인 할 필요 없이, 클라이언트에서 DB에 저장해야 하는 이벤트 발생시 DB로 저장하면, 서버가 20개의 클라이언트에 일일히 이벤트 발생 여부를 확인할 필요가 없습니다. 즉 이벤트를 확인하고 db에 저장하는 과정을 구현할 필요도 없습니다.

4.사용자가 실시간 Web 모니터링 화면에 접속한 경우 COSMOS(서버 프로그램)은 주기적(1초)으로 계측기(클라이언트)에 데이터를 요청 후, 받아서 Web화면으로 전달하고사용자가 다른 화면으로 이동하면 Connection 종료

RE: 지금 원하시는 내용이 정확히, SignalR Hub로 실시간 통신을 하는 패턴입니다.

낮에 말씀드린 내용과 합쳐서 말씀드리자면

  1. 계측기(클라이언트)는 이벤트 발생시 DB table에 내용 저장
  2. 사용자가 실시간 모니터링(Web 페이지) 접속시
    2-1) SignalR Hub 웹소켓 방식으로 웹과 서버 연결
    2-2) SqlDependency 객체를 인스턴싱하여, 이벤트를 로깅하는 테이블을 계속 관제
    2-3) 웹 화면에 보여줘야될 내용이 SqlDependency로 관제 되었다면, 내용 가공 후 SignalR Hub를 통해 웹 화면에 전달
    2-4) 서버로부터 전달받은 데이터로 모니터링 화면(아마도 켄버스나 테이블 또는 차트) 부분 렌더링
2 Likes

네. 알겠습니다.
답변 감사드립니다.

1 Like

계측기는 Client 기능이 없고 Server 기능만 있어서
말씀하신 1번( 1. 계측기(클라이언트)는 이벤트 발생시 DB table에 내용 저장) 부분이
불가한 상태입니다. ㅠㅠ

답변 감사드립니다.

2 Likes

흠… 그러셔도 계측기에 이벤트가 발생했다면 어딘가엔 그 내용이 저장되지 않나요? 보통 따로 로그 파일에 저장할거 같은데…
어떤식으로 저장되 있고, 어떻게 가져올 것이냐에 따라 개발 내용이 달라질거 같습니다.

1 Like
  1. 계측데이터는 계측기(서버)에 접속해서 데이터를 요청해야
    계측데이터를 보내주는 구조입니다.

  2. 이벤트 데이터는 주기적으로 계측기에 접속해서
    이벤트가 발생했는지 여부를 체크하는 데이터를 요청해서
    이벤트가 발생한 경우 해당 내용을 요청하는 데이터를 보내야
    해당 이벤트 내용을 보내주는 구조입니다.

답변 감사드립니다.

1 Like

개략적으로 완전 동일한 구조의 프로젝트 개발경험이 있습니다.
대량의 Socket통신이니 구현하려는사항들은 뭐 그냥 OOP, async 등 그냥 패러다임에 대한 공부를 많이하셔서 당연히 되게 만드셔야 될 영역같네요
더 도움드리는건 문제될수도있을거같아서 어렵고 제가 전하고싶은건
위 구조를 구현하는데 필요한 선물같은기능들이 최신닷넷코어에 모조리 담겨 있습니다. 각잡고 파보시면 어떨까 싶어요

3 Likes

와… 선물 같은 기능 표현 고급지네용 >ㅁ<b

3 Likes

답변 감사드립니다.

2 Likes