사용자와 장비 사이에 껴서 원격으로 장비의 데이터를 확인할 수 있게 해주는 HMI라는 녀석은
장비가 없으면 깡통에 불과하다.
그 깡통인 HMI를 유지보수하는 게 주 업무 중 하나인데,
불특정 시간마다 되면 PC 프로그램과 장비의 연결이 끊긴다는 내용을 전달 받았다.
일반적인 인터넷 환경과 달리
이런 전기 산업 쪽 장비는 HMI가 클라이언트가 되어 서버 역활을 하는 장비에게 데이터를 요청하고,
요청을 받은 장비는 내부 메모리 데이터를 긁어다가 패킷을 보내준다.
HMI 프로그램은 받은 데이터를 해석하고, 맵핑하여 사용자에게 전시하는 역활을 하고,
사용자 조작을 반대로 장비로 전송하기도 한다.
하지만 그 과정에서 누군가가 연결을 끊어버려 그 절차가 진행되지 않는 것.
처음에는 일반적인 인터넷 환경을 상정하고 PC SW가 서버, 장비가 클라이언트라 생각했으나
PC 측의 연결 함수를 아무리 뜯어봐도 서버 역활을 하는 것 같지는 않았다.
소캣 연결 절차를 따라가봐도 내가 상대방에게 요청하는 것 밖에 없네?
...내 생각이 잘못된걸 그때서야 알았다. 아 이거 완전 반대구나.
내 환경에서는 죽어도 재현이 안됐기에 고민 끝에 다음과 같은 방식으로 증상을 재현하였다.
1. 우선 PC와 연결할 때는 장비 전원을 켜둔다. (소켓 열림)
2. 데이터를 한번 요청하여 화면에 제대로 표시되는 지 확인한다.
3. 장비 전원을 껐다가 다시 켠 후 데이터를 요청하여 전달받은 문제가 발생한지 확인한다.(소켓 닫힘)
실제 원인은 이랬다.
모종의 이유로 장비 측에서 PC 프로그램과의 소켓을 끊어버린 것.
PC 프로그램은 별도의 소켓 Life Check를 진행하지 않고 있기 때문에
데이터 값이 문제 있다는 오류 메세지만 출력되고 있었다.
그 상황에서 연결 설정을 통해 다시 연결하고 데이터를 요청하면 정상적으로 받아왔다.
그렇다고 나는 FW 개발자가 아니니 장비 소스코드를 뜯어볼 수도 없는 노릇.
그래서 PC 프로그램의 연결 소스코드를 수정하여 해결하기로 했다.
C#의 Socket 클래스를 살펴본 봐 Poll과 Available 이라는 기능이 있는 걸 알 수 있었다.
Poll은 인자로 최대 시간(MS)와 Mode를 받아 결과를 반환한다.
- SelectMode.SelectRead: 소켓이 읽기 가능한 상태인지 확인.
- SelectMode.SelectWrite: 소켓이 쓰기 가능한 상태인지 확인.
- SelectMode.SelectError: 소켓에 오류가 있는지 확인.
Available 은 소켓에 수신 대기중인 바이트가 얼마나 있는지 감지하는 기능이다.
해당 함수를 활용하면 소켓 연결을 확인할 수 있을 것으로 생각 되어 코드를 아래와 같이 작성하고 적용하였다.
우선 통신 연결이 처음 성공하면 모니터링 함수를 통해 1초 간격으로 소켓 상태를 확인하고
수신 대기중인 바이트를 계산하여 0바이트인지 확인한다.
Poll과 Available의 결과가 true로 반환되어 소켓 닫힘이 감지되면 아래의 재 연결 함수로 이동하게 된다.
해당 함수는 소켓 연결을 재 시도하고, 오류가 발생하면 5초 뒤에 다시 시도하는 역활을 하게 된다.
해당 작업된 결과물 송부해서 지금까지도 기다려본 바,
다행이 별 다른 피드백은 없는 것으로 보아하니...
고안했던 방법이 잘 먹힌 거 같다.
2주~3주 넘게 고민했는데 쉽게 풀려서 정말 다행였다랄까.
'Tech > C#' 카테고리의 다른 글
C#의 정수형 나눗셈시 주의사항. (1) | 2025.02.21 |
---|