Java NIO-ServerSocket 채널

Java NIO 서버 소켓 채널은 다시 소켓을 연결하는 스트림 지향 데이터 흐름에 사용되는 선택 가능한 유형 채널입니다. 서버 소켓 채널은 정적을 호출하여 생성 할 수 있습니다. open() 메소드, 기존 소켓 제공이 아직 존재하지 않는 경우 서버 소켓 채널은 open 메소드를 호출하여 생성되지만 아직 바인딩되지 않았습니다. 소켓 채널을 바인딩하기 위해 bind() 메서드가 호출됩니다.

여기서 언급해야 할 점은 채널이 바인딩되지 않은 상태에서 I / O 작업을 시도하면이 채널에서 NotYetBoundException이 발생하므로 IO 작업을 수행하기 전에 채널이 바인딩되었는지 확인해야합니다.

서버 소켓 채널에 대한 수신 연결은 ServerSocketChannel.accept () 메서드를 호출하여 수신합니다. accept () 메서드가 반환되면 들어오는 연결과 함께 SocketChannel을 반환합니다. 따라서 accept () 메서드는 들어오는 연결이 도착할 때까지 차단됩니다. 채널이 비 차단 모드이면 accept 메서드는 보류중인 연결이 없으면 즉시 null을 반환합니다. 그렇지 않으면 새 연결을 사용할 수 있거나 I / O 오류가 발생할 때까지 무기한 차단됩니다.

새 채널의 소켓은 처음에 바인딩 해제됩니다. 연결이 허용되기 전에 소켓의 바인드 메소드 중 하나를 통해 특정 주소에 바인드되어야합니다. 또한 시스템 전체의 기본 SelectorProvider 객체의 openServerSocketChannel 메소드를 호출하여 새 채널을 생성합니다.

소켓 채널처럼 서버 소켓 채널은 다음을 사용하여 데이터를 읽을 수 있습니다. read()먼저 버퍼가 할당됩니다. ServerSocketChannel에서 읽은 데이터는 버퍼에 저장되고, 두 번째로 ServerSocketChannel.read () 메서드를 호출하고 ServerSocketChannel에서 데이터를 버퍼로 읽습니다. read () 메서드의 정수 값은 버퍼에 쓴 바이트 수를 반환합니다.

마찬가지로 데이터는 다음을 사용하여 서버 소켓 채널에 쓸 수 있습니다. write() 버퍼를 매개 변수로 사용하는 메소드. 일반적으로 Buffer에 쓸 수있는 바이트가 더 이상 없을 때까지 write () 메소드를 반복해야하므로 while 루프에서 write 메소드를 사용합니다.

소켓 채널의 중요한 방법

  • bind(SocketAddress local) −이 메서드는이 메서드에 매개 변수로 제공되는 로컬 주소에 소켓 채널을 바인딩하는 데 사용됩니다.

  • accept() −이 방법은이 채널의 소켓에 대한 연결을 수락하는 데 사용됩니다.

  • connect(SocketAddress remote) −이 방법은 소켓을 원격 주소에 연결하는 데 사용됩니다.

  • finishConnect() −이 방법은 소켓 채널 연결 과정을 완료하는 데 사용됩니다.

  • getRemoteAddress() −이 메서드는 채널의 소켓이 연결된 원격 위치의 주소를 반환합니다.

  • isConnected() − 이미 언급했듯이이 메서드는 소켓 채널의 연결 상태, 즉 연결 여부를 반환합니다.

  • open() − Open 메서드는 지정된 주소가없는 소켓 채널을 여는 방식으로, 이는 open () 메서드를 호출하고 결과 서버 소켓 채널에 대해 connect 메서드를 호출하고 원격으로 전달한 다음 해당 채널을 반환하는 것처럼 작동합니다.

  • read(ByteBuffer dst) −이 방법은 소켓 채널을 통해 주어진 버퍼에서 데이터를 읽는 데 사용됩니다.

  • setOption(SocketOption<T> name, T value) −이 방법은 소켓 옵션의 값을 설정합니다.

  • socket() −이 메서드는이 채널과 관련된 서버 소켓을 검색합니다.

  • validOps() −이 메서드는이 채널의 지원되는 작업을 식별하는 작업 집합을 반환합니다. 서버 소켓 채널은 새 연결 허용 만 지원하므로이 메서드는 SelectionKey.OP_ACCEPT를 반환합니다.

다음 예제는 Java NIO ServerSocketChannel에서 데이터를 보내는 방법을 보여줍니다.

C : /Test/temp.txt

Hello World!

클라이언트 : SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

산출

클라이언트를 실행하면 서버가 시작될 때까지 아무것도 인쇄되지 않습니다.

서버 : SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

산출

서버를 실행하면 다음이 인쇄됩니다.

Connection Set:  /127.0.0.1:49558
File Received