네트워크 입출력

네트워크

  • 여러 컴퓨터들을 통신 회선으로 연결한 것
  • LAN : 가정, 회사, 건물, 특정 영역에 존재하는 컴퓨터를 연결한 것(지역적)
  • WAN : LAN을 연결한 것(Router 사용) = 인터넷

alt text

서버와 클라이언트

  • 서버(Server) : 서비스를 제공하는 프로그램
  • 클라이언트(Client) : 서비스를 요청하는 프로그램
  • 인터넷에서 프로그램 통신 : (1) 클라이언트가 서비스 요청(2) 서버가 처리 결과 응답

IP 주소

네트워크 어댑터(LAN 카드)마다 할당되는 컴퓨터의 고유 주소

Port 번호

  • 운영체제가 관리하는 서버 프로그램의 연결 번호, 서버 시작 시 특정 Port 번호에 바인딩
  • 포트는 네트워크에 연결된 모든 장치에 표준화되며 각 포트에는 번호가 할당 ex) HTTP : 80, FTP : 21, DBMS : 1521

InetAdderss

  • 자바는 IP 주소를 java.net 패키지의 InetAddress로 표현

      InetAddress ia = InetAddress.getLocalHost();
    
  • getByName() : DNS에서 도메인 이름으로 등록된 단 하나의 IP 주소를 가져옴
  • getAllByName() : 등록된 모든 IP 주소를 배열로 가져옴
  • getHostAddress() : 객체에서 IP주소 얻기

TCP(Transmission Control Protocol)

  • 연결형 프로토콜 → 상대방이 연결된 상태에서 데이터를 주고 받는 전송용 프로토콜
  • 클라이언트가 연결 요청을 하고 서버가 연결을 수락하면 통신 회선 고정
  • 데이터는 고정 회선을 통해 전달, 보낸 데이터가 순서대로 전달되며 손실 발생 X
  • ServerSocket : 클라이언트의 연결을 수락하는 서버 쪽 클래스
  • Socket : 클라이언트에서 연결 요청할 때와 클라이언트와 서버 양쪽에서 데이터를 주고 받을 때 사용되는 클래스
  • 서버는 스레드 단위로 소켓을 생성한다.

alt text

  • TCP 서버 프로그램 개발
    1. ServerSocket 객체 생성 → ServerSocket은 Port를 가져야 한다. (임의로 50001번 지정)

       // 1-1
       ServerSocket server = new ServerSocket(50001); 
              
       // 1-2 : 서버에 여러 개의 네트워크가 있을 때, 특정 IP 주소를 명시적으로 지정 가능
       ServerSocket server = new ServerSocket(); 
       server.bind(new InetSocketAddress("192.16.180.xxx", 50001)); // bind() 메소드 사용
      
    2. Server 소켓이 생성되었다면 연결 요청의 수락을 위해서 server.accept() 실행

       // accept() 메소드는 클라이언트가 연결 요청하기 전까지 블로킹(=실행이 멈춘 상태)
       // 클라이언트의 요청이 들어오면 블로킹 해제 후, 통신용 Socket 리턴
       Socket socket = server.accept();
      
  • 클라이언트
    1. 클라이언트가 서버에 연결 요청을 하려면 Socket 객체를 생성하고 생성자 매개 값에 서버 IP, Port 제공(필수값)

       Socket socket = new Socket("IP", 50001);
      

입출력 스트림으로 데이터 주고 받기

  • 클라이언트가 연결 요청connect()을 하고 서버가 연결 수락 accept()을 했다면, 양쪽의 Socket 객체로부터 각각 InputStream과 OutputStream을 얻을 수 있다.

      InputStream is = socket.getInputStream();
      OutputStream os = socket.getOutputStream();
    

alt text

  • 쓰기 로직
    • 보낼 데이터를 byte[] 배열로 생성, 매개값으로 해서 Outputstream의 write() 호출

              
        String data = "보낼 데이터";
        byte[] bytes = data.getBytes("UTF-8");
        OutputStream os = socket.getOutputStream();
        os.write(bytes);
        os.flush();
      
    • 문자열을 더 간편하게 보내고 싶으면 보조 스트림 DataOutputStream 연결

        String data = "보낼 데이터";
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        dos.writeUTF(data);
        dos.flush();
      
  • 읽기 로직
    • 받은 데이터를 저장할 byte[] 배열을 하나 생성, 매개값으로 해서 InputStream의 read() 호출
    • read()는 읽은 데이터를 byte[] 배열에 저장하고 읽은 바이트 수 리턴

        byte[] bytes = new byte[1024];
        InputStream is = socket.getInputStream();
        int num = is.read(bytes);
        String data = new String(bytes, 0, num, "UTF-8");
      
    • 문자열을 더 간편하게 받고 싶으면 보조 스트림 DataInputStream 연결

        DataInputStream dis = new DataInputStream(socket.getInputStream());
        String data = dis.read(UTF);