현재 위치 - 법률 상담 무료 플랫폼 - 특허 조회 - 자바 비동기 프로그래밍
자바 비동기 프로그래밍
비동기 iostream 을 사용하여 소켓 프로세스 통신 프로그램 작성

Merlin 에는 비동기 입력 출력 메커니즘을 구현하는 응용 프로그램 인터페이스 패키지인 java.nio (많은 기본 유형의 버퍼를 정의하는 새로운 입력 출력 패키지), java.nio.channels (채널, 선택기 등) 가 추가되었습니다. , 비동기 입력 및 출력) 및 java.nio.charset (문자 인코딩 및 디코딩) 에 사용됩니다. 채널은 먼저 선택기에 관심 있는 이벤트를 등록하고 해당 이벤트가 발생할 때 선택기는 SelectionKey 를 통해 등록된 채널에 알립니다. 그런 다음 채널은 버퍼를 통해 보류 중인 정보를 패키지화하고 인코딩/디코딩하며 입/출력 제어를 완료합니다.

채널 소개:

이 문서에서는 ServerSocketChannel 과 SocketChannel 을 주로 소개합니다. 둘 다 선택 채널로, 동기식 모드와 비동기식 모드 모두에서 각각 작동할 수 있습니다 (여기서 선택 사항은 두 가지 작업 모드를 선택할 수 있는 것이 아니라 원하는 이벤트를 선택적으로 등록할 수 있습니다). 채널을 사용할 수 있습니다. ConfigureBlocking (Boolean) 은 작업 모드를 설정합니다. ServerSocketChannel 은 이전 버전의 API 에 비해 ServerSocket 에 해당하고 SocketChannel 은 Socket 에 해당합니다. 채널이 동기화 모드에서 작동하는 경우 프로그래밍 방법은 기본적으로 이전과 유사합니다. 여기서는 비동기 작업 모드에 대해 설명합니다.

비동기 I/O 메커니즘이란 I/O 를 처리할 때 I/O 가 완료될 때까지 기다릴 필요가 없다는 것입니다. 따라서 비동기 동의어는 차단되지 않았습니다. 서버측에서 ServerSocketChannel 은 정적 함수인 open () 을 통해 인스턴스 serverChl 을 반환합니다. 그런 다음 채널은 serverChl.socket () 을 호출합니다. Bind () 는 서버 포트에 바인딩되고 register (selector sel, selectionkey) 가 호출됩니다. OP_ACCEPT) 선택기에 OP_ACCEPT 이벤트를 등록합니다 (ServerSocketChannel 은 op _ accept 이벤트만 등록할 수 있음). 고객이 접속을 요청하면 선택기는 채널에 고객 접속 요청이 있음을 알려 적절한 입출력 제어를 수행합니다. 클라이언트에서 클라이언트 Chl 인스턴스가 관심 있는 이벤트 (op _ connect, op _ read 및 op _ write 의 조합) 를 등록한 후 클라이언트 CHL 을 호출합니다. Connect (inetsocketaddress) 는 서버에 연결하여 적절하게 처리합니다. 여기서 연결은 비동기적입니다. 즉, 즉시 되돌아가 다음 코드를 계속 실행합니다.

선택기 및 선택 키 소개:

선택기의 역할은 채널에 관심 있는 이벤트를 즉시 애플리케이션에 제출하지 않고 등록된 채널 요청이 처리할 때까지 대기시키는 것입니다. 즉, 선택기는 언제든지 준비된 채널을 FIFO 순으로 보고합니다. 그렇다면 선택기는 무엇을 통해 보고합니까? 키를 선택합니다. 키를 선택하는 기능은 어떤 채널이 준비되었는지, 무엇을 하는지 나타내는 것이다. 여러분은 이것이 분명히 등록 채널에 관심이 있는 사건이라고 생각하실 수 있을 겁니다. (존 F. 케네디, 채널, 채널, 채널, 채널, 채널, 채널) 예. 예를 들어 서버측 serverChl 의 경우 key.isAcceptable () 을 호출하여 serverChl 에 클라이언트 연결 요청이 있음을 알릴 수 있습니다. 해당 기능은 선택 키입니다. Isreadable (), selectionkey 입니다. Isreatable () 을 참조하십시오. 일반적으로 관심 있는 이벤트는 루프에서 폴링됩니다 (자세한 내용은 아래 코드 참조). 선택기에 채널 등록 이벤트가 발생하지 않으면 이벤트가 발생할 때까지 Selector.select () 호출이 차단됩니다. 또는 selectNow () 또는 select (긴 시간 초과) 를 호출할 수 있습니다. 전자는 즉시 반환되고, 이벤트가 없을 때는 0 을 반환합니다. 후자는 시간이 초과되어 반환됩니다. 선택기는 최대 63 개의 채널에서 동시에 사용할 수 있습니다.

적용 예:

다음은 비동기 입/출력 메커니즘으로 구현된 클라이언트/서버 샘플 프로그램입니다. 프로그램 목록 1 (편폭으로 서버 측 구현만 제공하며 독자는 클라이언트 코드를 참조할 수 있음).

프로그램 클래스 다이어그램

공용 클래스 NBlockingServer {

Int port = 8000

Intbuffer size =1024;

선택기 selector = null

Server socket channel server channel = null;

HashMap clientChannelMap = null// 각 클라이언트 연결에 해당하는 소켓과 채널을 저장합니다.

공용 NBlockingServer( int 포트) {

This.clientchannelmap = newhashmap ();

This.port = port

}

공용 void initialize () 로 인해 IOException {

//초기화: 선택기는 개별적으로 인스턴스화되고 서버는 채널을 선택할 수 있습니다.

This.selector = 선택기. open ();

This.serverchannel = server socketchannel.open ();

This.serverchannel.configureblocking (false);

Inetaddress localhost = inetaddress.getlocalhost ();

Inetsocketaddress isa = new inetsocketaddress (localhost, this.port);

This.serverChannel.socket () 을 참조하십시오. Bind (isa); //소켓을 서버의 사용 가능한 포트에 바인딩합니다.

}

//마지막으로 자원 확보

공용 void finalize () 로 인해 IOException {

This.serverchannel.close ();

This.selector.close () 를 참조하십시오.

}

//바이트 버퍼로 읽은 정보 디코딩

공용 문자열 디코딩 (ByteBuffer byteBuffer) 이 발생합니다

문자 인코딩 예외 {

Charset charset = charset.forname ("iso-8859-1");

Charset decoder decoder = charset.newdecoder ();

Char buffer char buffer = decoder.decode (byte buffer);

문자열 result = charbuffer.tostring ();

결과를 반환합니다.

}

//수신 포트, 채널이 준비되면 적절한 작업을 수행합니다.

Public void portListening () 은 IOException, InterruptedException {

//서버측 채널 등록 OP_ACCEPT 이벤트.

Selectionkey accept key = this.serverchannel.register (this.selector,

키를 선택합니다. Op _ accept);

//등록된 이벤트가 발생할 때 select () 의 반환 값은 0 보다 큽니다.

While (acceptKey.selector (). 선택 () > 0) {

System.out.println ("이벤트 발생");

//준비된 모든 선택 키를 가져옵니다.

Set readykeys = this.selector.selectedkeys ();

//반복자를 사용하여 선택 키를 폴링합니다.

반복자 I = readykeys.iterator ();

그리고 (나

Else if (key.isReadable()) {// 채널 읽기 준비 이벤트인 경우 ,

System.out.println ("읽을 수 있음");

//선택 키에 해당하는 채널과 소켓을 가져옵니다.

SelectableChannel nextReady =

(selectablechannel) key.channel ();

소켓 소켓 = (소켓) key.attachment ();

//이 이벤트를 처리합니다. 처리 메서드는 ClientChInstance 클래스에 캡슐화되어 있습니다.

This.readfromchannel (socket.getchannel (),

(클라이언트 인스턴스)

This.clientchannelmap.get (소켓));

}

Else If(key. is write able()){// 채널 쓰기 준비 이벤트인 경우 ,

System.out.println ("writeable");

//소켓 획득 후 사후 처리 (위 참조).

소켓 소켓 = (소켓) key.attachment ();

소켓 채널 채널 = (소켓 채널)

Socket.getchannel ();

This.writeToChannel( channel, "이건 서버에서 온 거야!" " );

}

}

}

}

//채널 쓰기 작업

Public void write to channel (소켓 채널, 문자열 메시지)

Ioexception 발생 {

Bytebuffer buf = bytebuffer.wrap (message.getbytes ());

Intnbytes = channel.write (buf);

}

//채널의 읽기 작업

Public void readfromchannel (socket channel channel, clientchininstance client instance)

IOException, InterruptedException {

Bytebuffer bytebuffer = bytebuffer.allocate (buffer size);

Intnbytes = channel.read (bytebuffer);

Bytebuffer.flip ();

문자열 결과 = this.decode (bytebuffer);

//클라이언트가' @exit' 종료 명령을 실행할 때 채널을 닫습니다.

If (result.indexof ("@ exit") > = 0) {

Channel.close ();

}

그렇지 않으면 {

Clientinstance.append (result.tostring ());

//한 줄을 읽은 후 적절한 작업을 수행합니다.

If (result.indexof ("\ n") > = 0 ){

System.out.println ("클라이언트 입력"+결과);

Clientinstance.execute ();

}

}

}

//이 클래스는 execute () 메서드를 다시 로드하여 클라이언트 작동 방식을 캡슐화합니다.

공용 클래스 ClientChInstance {

SocketChannel 채널;

Stringbufferbuffer = new stringbuffer ();

공용 클라이언트 인스턴스 (소켓 채널) {

This.channel = 채널;

}

Public void execute () 에서 IOException {

String message = "채널에서 읽은 응답입니다!" 을 눌러 섹션을 인쇄할 수도 있습니다

WriteToChannel( this.channel, message);

Buffer = new stringbuffer ();

}

//한 행이 끝나지 않은 경우 현재 단어를 버퍼 끝에 놓습니다.

공용 void 추가 (문자열 값) {

Buffer.append (값);

}

}

//마스터 프로그램

공용 정적 void main( String[] args) {

Nblockingserver nbserver = new nblockingserver (8000);

시도 {

Nbserver.initialize ();

} catch (예외 e) {

E. printstacktrace ();

System.exit (-1);

}

시도 {

Nbserver.portlistening ();

}

캡처 (예외 e) {

E. printstacktrace ();

}

}

}

프로그램 목록 1

요약:

위의 프로그램 세그먼트에서 볼 수 있듯이 서버는 중복 스레드를 도입하지 않고 다중 클라이언트의 클라이언트/서버 모드를 완료했습니다. 이 프로그램에서 콜백 모드가 사용되었습니다. 두 패키지가 어떤 이유로 호환되지 않기 때문에 원래 입출력 패키지와 새로 추가된 입출력 패키지를 혼합하지 않도록 주의해야 합니다. 즉, 채널을 사용할 때 버퍼를 사용하여 입/출력 제어를 완료합니다. 이 프로그램은 Windows 2000 및 J2SE 1.4 에서 텔넷 테스트를 통과했습니다.