ecsimsw

Net 본문

Net

JinHwan Kim 2019. 1. 23. 14:24

Socket

- Tcp 포로토콜 기반의 소켓 프로그래밍을 지원하는 Net 모듈에 대해서 공부하고 스트림을 통해 c# 응용프로그램과 통신할 것이다.
 
  • net / socket
     
    - net 모듈은 소켓 객체를 이용하여 서버와 클라이언트의 소켓 객체를 생성 가능하다.
     
      net.connect()와 net.createConnection() 호출을 통해 클라이언트를 서버에 연결을 할 수 있고, 이렇게 클라이언트와 서버가 연결되는 시점에 서버에 socket 객체가 생성된다.
     
      만들어진 소켓은 stream 이면서 동시에 event emitter 인데, 이는 데이터를 스트림을 통해 데이터를 읽고 쓰기가 가능하며 이벤트 핸들러를 사용하여 데이터를 처리할 수도 있다.
     
    - net 모듈은 설치가 필요없이 위처럼 바로 require하여 사용할 수 있다.
  • createServer / address / listen
     
    - 서버는 다음처럼 net.createServer 메소드를 통해 성성한다.
     
    - createServer를 통해 생성된 socket 객체를 통해 데이터와 이벤트를 처리한다.
     
    server.address는 서버의 주소와 주소 패밀리 이름, 포트를 반환한다. 위 예시에서는 port만을 출력하였다.
     
    server.listen은 해당 port로 연결을 수신한다. 함수는 비동기 함수이고, 서버가 바인딩되면 'listening' 이벤트가 발생한다.
  • socket.write
     
    - 소켓에 데이터를 보낼 때는 socket.write 메소드를 사용한다.
     
      스트림으로 데이터를 보내고 성공 시 true, 실패 시 false 를 반환한다. 데이터가 최종적으로 작성되면 callback 함수가 실행된다.
  • socket.close / socket.pause
     
    server.close 메소드는 서버가 더 이상 요청을 받지않고 close 이벤트를 발생시킨다.
    server.pause() 메소드는 서버가 지정 시간 동안 요청 받기를 멈춘다. 파라미터로 아무것도 안줄 시 socket.resume() 이전까지 요청을 받지 않고, 파라미터로 밀리세컨드 시간을 입력하여 해당 시간동안 요청 받기를 멈출 수 도 있다.
  • socket event
    - net.socket은 eventEmitter의 인스턴스라서 socket.on('eventName',handler) 메소드를 통해 이벤트를 처리할 수 있다. 아래는 주요 이벤트를 나열하였다.
    conncet : 소켓이 연결되면 발생한다.
    data : 소켓에서 데이터를 받을 시 발생한다. 콜백 함수에서 버퍼/문자열 data 파라미터를 처리할 수 있다.
    end : 소켓 반대편에서 FIN 패킷을 보냈을 시 발생한다.
    err : 오류 발생 시 발생한다. close 이벤트가 이어 발생한다.
    close : 소켓이 완전히 닫혔을 시 발생한다.
    timeout : 소켓의 시간이 만료되었을 때 발생한다.
    drain : 작성 버퍼가 비워졌을 때 발생한다.
  • Chatting app _server
    - 이런 이벤트를 통해 소켓으로 데이터를 받고 이를 연결된 모든 소켓에 뿌리는 서버를 만들 수 있다.
     
    1) net.createServer를 호출하므로서 socket 객체를 생성한다. 생성된 소켓은 clients 배열에 push 한다. socket 객체를 통해 소켓으로 직접 연결된 클라이언트를, clients 배열을 통해 연결된 전체 클라이언트들(소켓들)을 관리할 수 있다.
     
    2) 'data' 이벤트 핸들러를 통해 한 socket을 통해 data가 들어오면 write 메소드를 통해 clients의 모든 객체에 데이터를 뿌린다.
     
    3) 'end' 이벤트 핸들러를 정의하여 클라이언트가 연결을 종료하면 clients 배열에서 해당 소켓의 인덱스를 확인하여 제거하고 splice한다.
  • Chatting app _ client (winform)
      클라이언트는 c# 윈폼으로 만들어보았다. 자세한 설명은 c# 카테고리나 project에서 소개하는 것으로 하고 node.js 포스팅에선 놓치기 쉬운 것만 확인할 것이다.
     
    1) 멀티 스레딩 : 수신 함수를 만들어 Receive_thread에 델리게이트의 인자로 넣으므로써 비동기 송수신을 가능하도록 하였다.
     
      2) string을 byte로 encoding 하여 write 메소드를 통해 데이터를 전송하고, 수신 시엔 반대로 byte를 string으로 encoding 하여 수신 데이터를 얻었다.
     
      3) form 종료 시 NetworkStream과 TcpClient를 종료하므로써 end 이벤트를 서버에 발생시켰다. 이를 빼먹을 시 클라이언트 종료 시 에러가 발생하여 서버가 아예 닫히는 상황이 발생한다. Sleep(2000)은 2초의 딜레이를 주고 다음 동작을 실행 시킨다. close가 너무 빠르면 서버에서 에러가 나서 일부러 딜레이를 주었다. 서버에서의 data 이벤트가 처리되는 도중에 클라이언트가 close로 닫혀버리면 서버가 사라진 클라이언트를 찾을 수 없어서 나는 오류 같았다.
     
      stream.write의 동기/ 비동기를 고민했으나 어차피 클라이언트는 write를 다 마치고 close를 호출하고, 그때 서버가 데이터를 보내고 있나, 데이터 전송을 종료했나의 문제지 클라이언트의 write 속도 문제는 아니라고 판단하였고,
     
      서버에서 end 이벤트를 처리함과 동시에 ~ is left 를 나머지 클라이언트에 뿌리는 방식이 가장 좋다고 생각했으나 그럼 서버 입장에서 모든 클라이언트의 데이터를 클라이언트 id+message 형식으로 관리해줘야하므로 딜레이를 주는 것으로 해결 했으나,
     
      클라이언트가 엄청 많아져 데이터 전송에 2초 이상의 시간이 걸리거나, data 이벤트 처리에서 다른 처리가 추가 될 경우 등, Sleep()으로 딜레이를 주는 것에는 분명히 한계가 있어 다음번 채팅 어플리케이션은 이를 해결할 방법을 고민할 생각이다.
  •  

'Server application > Node.js' 카테고리의 다른 글

Socket.io  (0) 2019.01.22
GET / POST  (0) 2019.01.20
FileStream / Querystring  (0) 2019.01.19
Serving static files / Grave accent  (0) 2019.01.16
Template engine / pug  (0) 2019.01.15
Comments