1. NIO 라이브러리 소개
1. 버퍼 버퍼
버퍼는 작성하고 읽을 데이터가 포함 된 객체입니다.
NIO에서 모든 데이터는 버퍼로 처리됩니다. 데이터를 읽을 때 채널에서 버퍼로 직접 읽히고 데이터를 작성할 때 버퍼에서 채널로 기록됩니다.
버퍼는 본질적으로 배열, 일반적으로 바이트 어레이 (바이트 버퍼) 또는 기타 유형의 배열입니다. 또한 버퍼는 데이터에 대한 구조화 된 액세스 및 읽기 및 쓰기 위치 유지와 같은 정보를 제공합니다.
버퍼 클래스의 상속 관계는 아래 그림에 나와 있습니다.
2. 채널
채널은 네트워크 데이터를 채널을 통해 읽고 작성하는 채널입니다. 채널과 스트림의 차이점은 채널이 양방향 (채널을 사용하여 후자를 동시에 읽고 쓰는 데 사용될 수 있음)이며 스트림은 한 방향으로 만 움직입니다.
채널은 네트워크 읽기 및 쓰기 용 SelectableChannel (Serversocketchannel 및 Socketchannel은 하위 클래스), 파일 작업 용 Filechannel의 두 가지 범주로 대략적으로 나눌 수 있습니다.
다음 예제는 filechannel을 사용하여 파일에 데이터를 작성하고 파일의 데이터를 읽고 파일 데이터를 다른 파일로 복사합니다.
public class niotest {public static void main (String [] args)은 ioexception {copyfile (); } // 파일을 복사 개인 static void copyfile () {fileInputStream in = null; fileoutputStream out = null; try {in = new FileInputStream ( "src/main/java/data/in-data.txt"); out = new FileOutputStream ( "SRC/MAIN/JAVA/DATA/OUT-DATA.TXT"); filechannel eNcannel = in.getChannel (); filechannel outChannel = out.getChannel (); 바이트 버퍼 버퍼 = Bytebuffer.allocate (1024); int bytesRead = Zannel.Read (버퍼); while (bytread! = -1) {buffer.flip (); OutChannel.write (버퍼); buffer.clear (); BytesRead = inchannel.read (버퍼); }} catch (filenotfoundException e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }} // 쓰기 파일 쓰기 개인 정적 void writefilenio () {try {randomaccessfile fout = new randomAccessFile ( "Src/main/java/nio-data.txt", "rw"); filechannel fc = fout.getChannel (); 바이트 버퍼 버퍼 = Bytebuffer.allocate (1024); buffer.put ( "hi123".getBytes ()); buffer.flip (); try {fc.write (버퍼); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }} catch (filenotfoundException e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }} // 파일 읽기 개인 static void ReadFilenio () {fileInputStream fileInputStream; {fileInputStream = new FileInputStream ( "SRC/MAIN/JAVA/DATA/NIO-DATA.TXT"); filechannel filechannel = fileInputStream.getChannel (); // fileInputStream bytebuffer bytebuffer = bytebuffer.allocate (1024)에서 채널을 가져옵니다 int int bytesread = filechannel.read (bytebuffer); // (bytesread! */ bytebuffer.flip (); // hasRemaining () : (bytebuffer.hasremaining ()) {system.out.print ((char) bytebuffer.get ()); } /** 버퍼를 지우십시오* 위치 = 0; * 한계 = 용량; */ bytebuffer.clear (); BYTESREAD = FILECHANNE.READ (BYTEBUFFER); }} catch (filenotfoundException e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }}}3. 멀티플렉서 선택기
멀티플렉서는 준비된 작업을 선택할 수있는 기능을 제공합니다. 선택기는 등록 된 채널을 지속적으로 투표합니다. 채널이 읽기 또는 쓰기 이벤트를 보내면 채널은 준비 상태에 있으며 선택기가 여론 조사됩니다. 그런 다음 선택 키를 통해 준비된 채널 세트를 얻을 수있어 후속 I/O 작업을 수행 할 수 있습니다.
멀티플렉서 선택기는 동시에 여러 채널을 폴링 할 수 있습니다. JDK는 기존의 선택 구현 대신 epoll을 사용하기 때문에 최대 연결 핸들 1024/2048의 한계가 없으므로 하나의 스레드 만 선택기 여론 조사를 담당해야하며 수천 명의 클라이언트에 액세스 할 수 있습니다. 모델은 아래 그림에 나와 있습니다.
단일 스레드로 선택기를 처리하십시오. 선택기를 사용하려면 선택기에 채널을 등록한 다음 select () 메소드를 호출해야합니다. 이 방법은 등록 된 채널에 이벤트가 준비 될 때까지 차단됩니다. 이 메소드가 돌아 오면 스레드는 새로운 연결, 데이터 수신 등과 같은 이러한 이벤트를 처리 할 수 있습니다.
메모:
1. 어떤 선택 모델?
Select는 이벤트 트리거링 메커니즘으로 대기 이벤트가 발생할 때 처리를 트리거하며 주로 Linux 서버 구현에 의해 클라이언트 처리에 사용됩니다.
장치가 이벤트를 트리거하거나 지정된 대기 시간을 초과 할 때까지 이벤트 (예 : 읽기 가능, 쓰기 가능, 높은 우선 순위 오류 출력 등)가 있는지 여부에 관계없이 비 블로킹을 지원하는 비 블로킹 IO 장치 세트를 동시에 감지 할 수 있습니다. 즉, 그들의 책임은 IO를 수행하는 것이 아니라 발신자가 현재 준비된 장치를 찾는 데 도움이됩니다.
2. 에폴 모델은 무엇입니까?
Epoll의 디자인 아이디어는 Select/Poll의 단일 작업을 1 epoll_create + Multiple epoll_ctrl + One Wait으로 분할하는 것입니다. 또한 커널은 Epoll 작업을 위해 파일 시스템 "EventPollfs"를 추가했습니다. 모니터링 할 각각의 파일 설명자는 해당 EventPollfs 파일 시스템의 inode 노드를 가지며 기본 정보는 EventPoll 구조에 저장됩니다. 모니터링 된 파일의 중요한 정보는 epitem 구조에 저장됩니다. 그래서 그들은 일대일 관계입니다.
2. NIO 서버 측 개발
기능 설명 : 서버 측을 켜고 각 액세스 클라이언트에 hello 문자열을 보냅니다.
서버 측 개발에 NIO를 사용하기위한 몇 가지 주요 단계가 있습니다.
1. serversocketchannel을 만들고 비 블로킹 모드로 구성하십시오
serversocketchannel = serversocketchannel.open (); serversocketchannel.configureBlocking (false);
2. 백 로그 크기와 같은 청취 및 구성 매개 변수를 바인딩하고 구성
serversocketchannel.socket (). bind (new inetSocketAddress (8080));
3. 멀티플렉서 선택기를 폴링하기위한 독립적 인 I/O 스레드 생성
4. 선택기 생성, 이전에 만든 Serversocketchannel을 선택기에 등록하고 selectionKey를 듣습니다.
selector = selector.open (); serversocketchannel.register (selector, selectionkey.op_accept);
5. I/O 스레드를 시작하고 루프 본체에서 selector.select () 메소드를 실행하고 준비된 채널을 폴링합니다.
(true) {등록한 이벤트에서 적어도 하나의 채널이 준비 될 때까지 (true) {// select () 블록을 등록 할 때까지 채널이 준비되지 않은 경우 여기에서 차단됩니다. // select (long timeout)은 시간 초과 밀리 초 (매개 변수)를 차단한다는 점을 제외하고 select (long timeout)은 select (long timeout)이 select (long timeout)가 동일합니다. selector.select (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); 부서지다; }}6. 준비 상태에서 채널을 폴링 할 때 판단해야합니다. OP_ACCEPT 상태 인 경우 새로운 클라이언트 액세스임을 의미합니다. 그런 다음 serversocketchannel.accept () 메소드를 호출하여 새 클라이언트를 수락하십시오.
// Ready SelectionKey를 반환 한 다음 반복하여 SET <SelectionKey> readKeys = selector.SelectedKeys (); for (iterator <selectionkey> it = readkeys.iterator (); it.hasnext ();) {selectionkey key = it.next (); it.remove (); try {if (key.isacceptable ()) {serversocketchannel server = (serversocketchannel) key.channel (); socketchannel client = server.accept (); client.configureBlocking (false); client.register (selector, selectionkey.op_write); } else if (key.iswritable ()) {socketchannel client = (socketchannel) key.channel (); 바이트 버퍼 버퍼 = Bytebuffer.allocate (20); 문자열 str = "hello"; 버퍼 = bytebuffer.wrap (str.getBytes ()); client.write (버퍼); key.cancel (); }} catch (ioexception e) {e.printstacktrace (); key.cancel (); try {key.channel (). close (); } catch (ioexception e1) {// todo 자동 생성 캐치 블록 e1.printstacktrace (); }}}7. 새로 액세스 한 클라이언트 링크 Socketchannel을 비 블로킹 모드로 설정하고 다른 TCP 매개 변수를 구성하십시오.
if (key.isacceptable ()) {serversocketchannel server = (serversocketchannel) key.channel (); socketchannel client = server.accept (); client.configureBlocking (false); ...}8. Socketchannel을 선택기에 등록하고 OP_WRITE를 듣습니다
client.register (selector, selectionkey.op_write);
9. 폴링 된 채널이 op_write 인 경우 데이터가 양말 채널로 작성되어야한다는 것을 의미합니다. 바이트 버퍼 객체가 구성되고 데이터 패킷이 작성됩니다.
else if (key.iswritable ()) {Socketchannel Client = (Socketchannel) key.channel (); 바이트 버퍼 버퍼 = Bytebuffer.allocate (20); 문자열 str = "hello"; 버퍼 = bytebuffer.wrap (str.getBytes ()); client.write (버퍼); key.cancel (); }전체 코드는 다음과 같습니다.
import java.io.ioexception; import java.net.inetSocketAddress; import java.nio.bytebuffer; import java.nio.channels.Cannels.ConectionKey; import java.nio.channels.selector; import java.nio.channels.selector; import java.nio.channels.serverocketchetchetchetchantal; java.nio.channels.socketchannel; import java.util.iterator; import java.util.set; public class serversocketchetchanneldemo {public static void main (string [] args) {serversocketchannel serverCchetchannel; selector = null; try {serversocketchannel = serversocketchannel.open (); serversocketchannel.configureBlocking (false); serversocketchannel.socket (). bind (new inetSocketAddress (8080)); selector = selector.open (); seversocketchanchann.register (selector, selectkey.op_accept); blocke.printstacktrace ();} while (true) {try {// select () 블록을 등록한 이벤트에 적어도 하나의 채널이 준비 될 때까지 // 채널 준비가 없으면 항상 여기에서 차단 될 것입니다 .//select (long timeout)는 select (parameters)를 차단할 것입니다. selector.select ();} catch (ioexception e) {// todo auto-auto-regenated catch blocke.printstacktrace (); break;} // ready selectionKey를 반환 한 다음 <selectionKey> readKeys = setector.selectedKeys (); for (iterator <SelectionKey> it = readkeys.); key = it.next (); it.remove (); try {if (key.isacceptable ()) {serversocketchannel server = (serversocketchannel) key.channel (); socketchannel client = server.accept (); client.register (selector, selector, selectionkey.op_write); client = (socketchannel) key.channel (); bytebuffer buffer = bytebuffer.allocate (20); String str = "hello"; buffer = bytebuffer.wrap (str.getBytes ()); client.write (buffer); key.cancel ();}} catch (ioxception e) {key.cancel (); {key.channel (). close ();} catch (ioexception e1) {// todo 자동 생성 캐치 Blocke1.printstacktrace ();}}}}}}}}}}Telnet LocalHost 8080을 사용하여 여러 클라이언트를 시뮬레이션합니다.
프로그램 실행 결과는 다음과 같습니다.
요약
위의 내용은이 기사에서 Java Nio 서버 측 개발에 대한 자세한 설명입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!