08. TCP 프로그래밍 02. 에코 클라이언트/서버 프로그래밍

08. TCP 프로그래밍

02. 에코 클라이언트/서버 프로그래밍.

에코는 말 그대로 메아리를 의미한다. 클라이언트가 보낸 데이터를 서버 쪽에서 받아들여, 클라이언트에게 그대로 다시 보내주는 것을 의미한다.

에코 서버

  1. 1001번 포트에서 동작하는 ServerSocket을 생성한다.
  2. ServerSocket의 accept() 메소드를 실행해서 클라이언트의 접속을 대기한다.
  3. 클라이언트가 접속할 경우 accept() 메소드는 socket 객체를 반환한다.
  4. 반환 받은 Socket으로부터 InputStream과 OutputStream을 구한다.
  5. InputStream은 BufferedReader 형식으로 변환하고OutputStream은 PrintWriter 형식으로 변환한다.
  6. BufferedReader의 readLine() 메소드를 이용해서 클라이언트가 보내는 문자열 한줄을 읽어 들인다.
  7. 6에서 읽은 문자열을 PrintWriter에 있는 println()을 이용해 다시 클라이언트로 전송한다.
  8. 6,7 작업을 반복한다. 클라이언트가 접속을 종료하게 되면 BufferedReader에 있는 readLine은 null을 반환한다.
  9. IO 객체와 소켓의 Close() 메소드를 호출한다.

에코 클라이언트

  1. Socket 생성자에 서버의 IP와 서버의 동작 포트 값(10001)을 인자로 넣어 생성한다. 소켓이 성공적으로 생성되었다면, 서버와 접속이 성공적으로 되었다는 것을 의미한다.
  2. 생성된 Socket으로부터 InputStream과 OutputStream을 구한다.
  3. InputStream은 BufferedReader 형식으로 변환하고 OutputStream은 PrintWriter 형식으로 변환한다.
  4. 키보드로부터 한 줄씩 입력 받는 BufferedReader 객체를 생성한다.
  5. 키보드로부터 한 줄을 입력 받아 PrintWriter에 있는 println()메소드를 이용해서 서버에게 전송한다.
  6. 서버가 다시 반환하는 문자열을 BufferedReader에 있는 readLine() 메소드를 이용해서 읽어 들인다. 읽어 들인 문자열은 화면에 출력한다.
  7. 4, 5, 6을 키보드로부터 quit 문자열을 입력 받을대까지 반복한다.
  8. 키보드로부터 quit 문자열이 입력되면 IO 객체와 소켓의 close() 메소드를 호출한다.
import java.net.*;
import java.io.*;

public class EchoClient{
    public static void main(String[] args){
        try{
            Socket sock = new Socket("127.0.0.1", 10001);
            BufferedReader keyBoard = new BufferedReader(new InputStreamReader(System.in));
            OutputStream out = sock.getOutputStream();
            InputStream in = sock.getInputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line = null;
            while((line = keyBoard.readLine()) != null){
                if(line.equals("quit")) break;
                pw.println(line);
                pw.flush();
                String echo = br.readLine();
                System.out.println("서버로부터 전달받은 문자열 :" +echo);
            }
            pw.close();
            br.close();
            sock.close();
        }catch (Exception e){
            System.out.println(e);
        }
    }
}
import java.net.*;
import java.io.*;

public class EchoServer{
    public static void main(String[] args){
        try{
            ServerSocket serverSocket = new ServerSocket(10001);
            System.out.println("접속을 기다립니다....");

            Socket sock = serverSocket.accept();
            InetAddress inetAddr = sock.getInetAddress();
            System.out.println(inetAddr.getHostAddress() + " 로 부터 접속했습니다.");

            OutputStream out = sock.getOutputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));

            InputStream in = sock.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));

            String line = null;
            while((line = br.readLine()) != null){
                System.out.println("클라이언트로 부터 전송받은 문자열 : "+line);
                pw.println(line);
                pw.flush();
            }
            pw.close();
            br.close();
            sock.close();
        }catch (Exception e) {
            System.out.println(e);
        }
    }
}

4. 에코 클라이언트와 에코 서버의 문제점

이 에코 서버의 문제점은 server는 하나의 클라이언트 접속만을 처리할 수 있다는 것이다. accept()로 대기하고 있다가 클라이언트의 접속 요청이 오면 클라이언트와 통신할 수 있는 소켓을 반환한 후, 다시 accept()하지 않기 때문이다.

출처 : 김성박 송지훈 공저, 『 자바 IO & NIO 네트워크 프로그래밍』, 한빛미디어(2004.9.30), 8장 인용.