자바

자바 NIO TCP 블로킹 채널 클라이언트 구현하기

알통몬_ 2017. 4. 20. 09:26
반응형


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

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

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

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

 


지난 포스팅에서는 NIO TCP 블로킹 채널을 이용해 서버를 구현해 보았는데요.

2017/04/19 - [자바] - 자바 NIO TCP 블로킹 채널로 채팅 서버 구현하기


이번 포스팅에서는 채팅 클라이언트를 구현해보겠습니다.


1. 클라이언트 클래스의 구조

public class ClientExample extends Application {

 SocketChannel socketChannel; // 클라이언트 통신을 위해 SocketChannel 필드 선언

 

 void startClient() { }

 

 void stopClient() { } 

 

 void receive() { }

 

 void send(String data) { }

 

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

 UI 생성 코드


2. startClient()

void startClient() {

  Thread thread = new Thread() { // 스레드 생성

   @Override

   public void run() {

    try { 

     socketChannel = SocketChannel.open(); // 소켓 생성 및 연결 요청

     socketChannel.configureBlocking(true);

     socketChannel.connect(new InetSocketAddress("localhost", 5001));

     Platform.runLater(()->{

      try {

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

       btnConn.setText("stop");

       btnSend.setDisable(false);

      } catch (Exception e) {}

     });

    } catch(Exception e) {

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

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

     return;

    }

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

   }

  };

  thread.start(); // 스레드 시작

 

 }


3. stopClient()

void stopClient() {

  try {

   Platform.runLater(()->{

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

    btnConn.setText("start");

    btnSend.setDisable(true);

   });

   if(socketChannel!=null && socketChannel.isOpen()) {

    socketChannel.close();

   }

  } catch (IOException e) {}

 

 } 


4. receive()

void receive() {

  while(true) {

   try {

    ByteBuffer byteBuffer = ByteBuffer.allocate(100);

    

    //서버가 비정상적으로 종료했을 경우 IOException 발생

    int readByteCount = socketChannel.read(byteBuffer); //데이터받기

    

    //서버가 정상적으로 Socket의 close()를 호출했을 경우

    if(readByteCount == -1) {

     throw new IOException();

    }

    

    byteBuffer.flip(); // 문자열로 변환

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

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

    

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

   } catch (Exception e) {

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

    stopClient();

    break;

   }

  }

 

 } 

5. send( String msg )

 void send(String msg) {

Thread thread = new Thread() { // 스레드 생성

@Override

public void run() {

try {

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

ByteBuffer byteBuffer = charset.encode(msg);

socketChannel.write(byteBuffer); // 서버로 데이터 보내기

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

} catch(Exception e) {

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

stopClient();

}

}

};

thread.start(); // 스레드 시작

 

}


6. UI 생성 코드

 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);

}

http://serviceapi.nmv.naver.com/flash/convertIframeTag.nhn?vid=6A77CF13B977B6869EBC0298BD90FA246E42&outKey=V1245ce02f6b589762446fde079d032b257449f03a663183dd34efde079d032b25744&width=544&height=306

위 링클를 클릭하시면 제가 네이버에서 포스팅 했었던 내용의 실행 영상을 보실 수 있습니다.


다음 포스팅에서는 TCP 블로킹 채널의 블로킹과 인터럽트에 대해 공부하겠습니다.

이상입니다.

반응형