티스토리 뷰

Skill/Programming - Network

21. 채널 (Channel)

gyulee0220 2019. 9. 27. 21:37

  Java NIO의 3번의 시리즈 마무리 채널에 대해 알아보자. 앞서도 간략히 설명했지만, Java NIO는 채널로 동작하게 된다.


1. 채널(Channel)이란?

  실제 네트워크 환경과는 살짝 다르지만 쉬운 예시를 들어 생각해보자. 기존의 Java I/O는 Blocking 하고, Java NIO는 Non-blocking 하다는 사실을 알고 있다. 그렇기에 Java IO에서 스레드에서 Reader와 Writer만 존재해, Reader로 블로킹을 하고, Writer로 블로킹을 풀어주면 된다.

 

Java IO



  하지만, Java NIO는 Non-blocking 방식이다. 따라서, 데이터를 주고 받기 위해서 스레드와 데이터가 들어간 버퍼사이의 일종의 터널을 만들어주어야 한다. 이것이 채널이 하는 역할이다.


Java NIO


  그리고 이 채널은 파일, 소켓, 데이터그램 등과 같은 다양한 I/O 소스로부터 데이터 블록을 버퍼로 쓰거나 읽어올 수 있다.


- 채널의 특징


  • Socket과 연결 되어, 입출력 역할을 수행한다
  • 입력과 출력을 동시에 수행한다.
  • Selector와 연결되어 있고, 하나에 Selector에는 다수의 채널이 존재할 수 있다.
  • Blocking 된 스레드를 깨우거나, 다시 Blocking할 수 있다.


2. Selector

  Java NIO는 하나의 스레드에 여러개의 연결이 있기 때문에 Selector를 이용해 어느 연결과 I/O를 실시할지 정할 Selector가 존재해야한다. Selector는 다른 기능을 하지 않고 어느 I/O에 연결할지 선택만 하게 된다. 



  Selector는 채널을 선택하는 기능을 하고, 선택된 채널이 스레드와 버퍼를 연결시켜 I/O를 진행하는 방식이 NIO의 매커니즘이라고 할 수 있다.


  일반적으로 새로운 Selector 생성에는 open() 메소드를 이용한다.


public static Selector open() throws IOException


  Selector에는 서로 다른 채널들이 등록되어야 하며 채널에 할당하기 위해 SelectionKey를 사용한다. 그 다음 프로그램에서 Selector 객체에 작업을 수행할 준비가 된 채널 키의 세트를 요청한다. 


   SelectionKey는 채널에서 포인터로 제공한다. Selector에 채널을 등록하게 되면 (register) SelectionKey를 반환하게 된다.


  그리고 Selector에 채널을 할당하기 위해서는 Selector가 아닌 채널에서 register() 메소드를 호출하면 된다.


public final SelectionKey register(Selector sel, int ops) throws ClosedChannelException



  int ops에는 총 4가지 옵션이 들어가게 된다. 각각은 SelectionKey에서 작동할 연산에 대해 명시하는 것이다. 


  • SelectionKey.OP_ACCEPT -> public fianl boolean isAcceptable()
  • SelectionKey.OP_CONNECT -> public fianl boolean isConnectable()
  • SelectionKey.OP_READ -> public fianl boolean isReadable()
  • SelectionKey.OP_WRITE -> public fianl boolean isWritable()


  

1
2
3
4
5
6
7
8
9
Selector selector = null;
        
try {
    ServerSocketChannel server = ServerSocketChannel.open();
    server.register(selector, SelectionKey.OP_ACCEPT);
            
catch (IOException ex) {
    System.err.println("error");
}
cs


3. SocketChannel 클래스

  SocketChannel 클래스는 Socket 객체와 연결되어 있다. 객체의 고급 설정을 위해 사용하게 된다. Socket의 수정이 필요한 경우 해당 클래스를 수정하면 된다.


- 연결하기


  SocketChannel과의 연결은 open() 메소드를 이용한다. 연결하려는 URL이 있다면은 해당 주소를 파라미터로 입력하면 된다.


public static SocketChannel open(SocketAddress remote) throws IOException


  만약 파라미터 없어 open() 메소드를 사용하게 되면, open으로 Channel의 실행만 실시하고, connect() 메소드를 통해 연결 할 수 있다.


public static SocketChannel connect(SocketAddress remote) throws IOException


- 읽기


  SocketChannel을 읽기 위해서는 앞서 생성한 ByteBuffer를 파라미터로 사용하면 된다. 메소드 명은 read()이다. 


public static SocketChannel read(SocketAddress remote) throws IOException


- 쓰기


  ByteBuffer에 데이터를 쓰기 위해서는 ByteBuffer를 파라미터로 사용하면 된다. 메소드 명은 write()이다. 


public abstract write(SocketAddress remote) throws IOException


- 종료하기


  일반적인 소켓처럼 사용이 끝나게 되면 포트와 리소스 해제를 위해 채널을 닫아주어야 한다. 메소드 명은 close()이다.


public void close() throws IOException


1
2
3
4
5
6
7
8
9
10
11
12
// Selector
Selector selector = null;
        
try {
    SocketChannel channel = SocketChannel.open();
    ByteBuffer buffer = ByteBuffer.allocate(100);
    int socket = channel.read(buffer); 
    channel.write(buffer);
            
catch (IOException ex) {
    System.err.println("error");
}
cs


4. ServerSocketChannel 클래스

  ServerSocketChannel 클래스는 들어오는 연결을 수용하기 위해 만들어졌다. 따라서, 이 클래스를 읽거나 쓸수 없고 연결도 불가능 하다. Selector에서 채널이 선택되면 연결의 알림을 받는 목적으로 사용되는 accept() 메소드만 사용할 뿐이다.


- 서버 소켓 채널 만들기


  open() 메소드를 통해 서버소켓을 만들 수 있다. 위에 있는 SocketChannel 클래스의 open()과는 차이가 존재한다. 서버 소켓 채널에서는 객체만 만들고 실제로 연결을 제공해주지 않는다. 연결은 다음과 같은 과정으로 실행된다. 


 public static ServerSocketChannel open() throws IOException


 - 연결 수용하기


  서버 소켓 채널 객체를 열면 accept()메소드를 통해 들어오는 연결을 대기 할 수 있다.


public abstract SocketChannel accept() throws IOException


  이를 이용해 서버 소켓 클래스를 만들게 된다면 다음과 같이 나타난다.


1
2
3
4
5
6
7
8
try {
    ServerSocketChannel server = ServerSocketChannel.open();
    ServerSocket socket = ServerChannel.socket();
    SocketAddress address = new InetSocketAddress(80);
    socket.bind(address);
catch (IOException ex) {
    System.err.println("error");
}
cs



'Skill > Programming - Network' 카테고리의 다른 글

23. UDP 클래스 및 입출력  (0) 2019.10.13
22. UDP (User Datagram Protocol)  (0) 2019.10.04
20. 버퍼 (Buffer)  (0) 2019.09.20
19. Java NIO (New IO)  (0) 2019.09.11
18. 서버 소켓 프로그래밍 예제 (Java)  (0) 2019.09.08
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
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
글 보관함