자바

자바 NIO 비동기 채널 채팅 클라이언트 만들기

알통몬_ 2017. 5. 4. 09:50
반응형


안녕하세요 알통몬입니다.

공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^

 

2017/05/04 - [자바] - 자바 NIO 비동기 채널 채팅 서버 만들기


클라이언트 클래스의 구조

public class ClientExample extends Application {

 AsynchronousChannelGroup channelGroup; // 비동기 채널 그룹 필드 선언

 AsynchronousSocketChannel socketChannel; // 비동기 소켓 채널 필드 선언

 

 void startClient() {// 연결 시작 코드}

 

 void stopClient() {//연결 끊기 코드 } 

 

 void receive() {//데이터 받기 코드}

 

 void send(String data) {//데이터 쓰기 코드}

 

 

 ///////////////////////////////////////////

        UI 코드 


1. startClient()

void startClient() {

  try {

   channelGroup = AsynchronousChannelGroup.withFixedThreadPool(

    Runtime.getRuntime().availableProcessors(),

    Executors.defaultThreadFactory()

   ); // CPU 코어 수만큼 스레드를 관리하는 스레드풀 생성하고 이것을 이용하느

                        비동기 채널 그룹 생성.

   socketChannel = AsynchronousSocketChannel.open(channelGroup);

                    //비동기 소켓 채널 생성.

   socketChannel.connect(new InetSocketAddress("localhost", 5001), null, new CompletionHandler<Void, Void>() {

    @Override

    public void completed(Void result, Void attachment) {

     Platform.runLater(()->{

      try {

       displayText("[연결 완료: "  + socketChannel.getRemoteAddress() + "]");

       btnConn.setText("stop");

       btnSend.setDisable(false);

      } catch (Exception e) {}

     });  

     receive(); // 서버에서 보낸 데이터 받기

    }

    @Override

    public void failed(Throwable e, Void attachment) {

     Platform.runLater(()->displayText("[서버 통신 안됨]"));

     if(socketChannel.isOpen()) { stopClient(); }

    }

   });

  } catch (IOException e) {}

 

 } 


2. stopClient()

 void stopClient() {

  try {

   Platform.runLater(()->{

    displayText("[연결 끊음]");

    btnConn.setText("start");

    btnSend.setDisable(true);

   });

   if(channelGroup!=null && !channelGroup.isShutdown()) {

    channelGroup.shutdownNow(); //비동기 채널 그룹에 포함된 모든 비동기 채널                                                                 닫음.

   }

  } catch (IOException e) {}

 

 } 


3. receive()

 void receive() {

  ByteBuffer byteBuffer = ByteBuffer.allocate(100);

  socketChannel.read(byteBuffer, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {

   @Override

   public void completed(Integer result, ByteBuffer attachment) {

    try {

     attachment.flip();

     Charset charset = Charset.forName("utf-8");

     String data = charset.decode(attachment).toString();

     Platform.runLater(()->displayText("[받기 완료] "  + data));

     

     ByteBuffer byteBuffer = ByteBuffer.allocate(100);

     socketChannel.read(byteBuffer, byteBuffer, this);

    } catch(Exception e) {}

   }

   @Override

   public void failed(Throwable exc, ByteBuffer attachment) {

    Platform.runLater(()->displayText("[서버 통신 안됨]"));

    stopClient();

   }

  });

 

 }


4. send(String data)

 void send(String data) {

  Charset charset = Charset.forName("utf-8");

  ByteBuffer byteBuffer = charset.encode(data);

  socketChannel.write(byteBuffer, null, new CompletionHandler<Integer, Void>() {

   @Override

   public void completed(Integer result, Void attachment) {

    Platform.runLater(()->displayText("[보내기 완료]"));

   }

   @Override

   public void failed(Throwable exc, Void attachment) {

    Platform.runLater(()->displayText("[서버 통신 안됨]"));

    stopClient();

   }

  });

 

 }


5. UI 생성 코드

JavaFX 포스팅 url

http://blog.naver.com/rain483/220605517395

 TextArea txtDisplay;

 TextField txtInput;

 Button btnConn, btnSend;

 

 @Override

 public void start(Stage primaryStage) throws Exception {

  BorderPane root = new BorderPane();

  root.setPrefSize(500, 300);

  

  txtDisplay = new TextArea();

  txtDisplay.setEditable(false);

  BorderPane.setMargin(txtDisplay, new Insets(0,0,2,0));

  root.setCenter(txtDisplay);

  

  BorderPane bottom = new BorderPane();

   txtInput = new TextField();

   txtInput.setPrefSize(60, 30);

   BorderPane.setMargin(txtInput, new Insets(0,1,1,1));

   

   btnConn = new Button("start");

   btnConn.setPrefSize(60, 30);

   btnConn.setOnAction(e->{

    if(btnConn.getText().equals("start")) {

     startClient();

    } else if(btnConn.getText().equals("stop")){

     stopClient();

    }

   });

   

   btnSend = new Button("send"); 

   btnSend.setPrefSize(60, 30);

   btnSend.setDisable(true);

   btnSend.setOnAction(e->send(txtInput.getText()));

   

   bottom.setCenter(txtInput);

   bottom.setLeft(btnConn);

   bottom.setRight(btnSend);

  root.setBottom(bottom);

  

  Scene scene = new Scene(root);

  scene.getStylesheets().add(getClass().getResource("app.css").toString());

  primaryStage.setScene(scene);

  primaryStage.setTitle("Client");

  primaryStage.setOnCloseRequest(event->stopClient());

  primaryStage.show();

 }

 

 void displayText(String text) {

  txtDisplay.appendText(text + "\n");

 } 

 

 public static void main(String[] args) {

  launch(args);

 }


네이버 블로그에 포스팅한 내용 중 실행 영상입니다.


반응형