Chapter 16 네트워킹(Networking)

1. 네트워킹(Networking)

  • 네트워킹(networking)이란 두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크network)를 구성하는 것을 말한다

1.1 클라이언트/서버(client/server)

  • '클라이언트/서버는 컴퓨터간의 관계를 역할로 구분하는 개념이다 서버(server)는 서비스를 제공하는 컴퓨터(service provider)이고 클라이언트(client)는 서비스를 사용하는 컴퓨터(service user)가 된다.
  • 네트워크를 구성할 때 전용서버를 두는 것을 서버기반모델 이라고 하고 각 클라이언트가 서버역할을 동시에 수행하는 것을 P2P모델 이라고 한다
  • 서버는 제공하는 서비스의 종류에 따라 파일서버 메일서버, 어플리케이션 서버 등이 있다
서버기반 모델(server-based model) P2P 모델(peer-to-peer model)
안정적인 서비스의 제공이 가능하다 서버구축 및 운용비용을 절감할 수 있다
공유 데이터의 관리와 보안이 용이 하다 자원의 활용을 극대화 할 수 있다
서버구축비용과 관리비용이 든다 자원의 관리가 어렵다
서버구축비용과 관리비용이 든다 보안이 취약하다

1.2 IP주소(IP Address)

  • IP주소는 컴퓨터를 네트워크 상에서 구별하는데 사용되는 고유한 값이며 4byte(32 bit)의 정수로 구성되어 있다
  • IP주소는 네트워크주소와 호스트 주소로 누눌 수 있으며 네트워크 주소가 같다는 것은 두 호스트가 같은 네트워크에 포함되어 있다는 것을 의미한다
  • IP Address에 Subnet Mask를 '&'연산을 해주면 네트워크 주소를 알 수 있다

| 192 | 168 | 10 | 100 | | 255 | 255 | 255 | 0 | |--|--|--|--| |11000000|10101000|00001010|01100100| |11111111|11111111|11111111|00000000| |11000000|10101000|00001010|01100100|

1.3 InetAddress

  • 자바에서는 IP주소를 다루기 위한 클래스로 InetAddress를 제공한다
import java.net.*;
import java.util.*;

public class Hello {

    public static void main(String[] args) {
        InetAddress ip = null;
        InetAddress[] ipArr = null;

        try{
            ip = InetAddress.getByName("www.daum.net");
            System.out.println("getHostName() :" + ip.getHostName());
            System.out.println("getHostAddress() :" + ip.getHostAddress());
            System.out.println("toString() :" + ip.toString());

            byte[] ipAddr = ip.getAddress();
            System.out.println("getAddress() :" + Arrays.toString(ipAddr));

            String result = "";
            for (int i=0; i < ipAddr.length; i++) {
                result += (ipAddr[i] < 0) ? ipAddr[i] + 256 : ipAddr[i];
                result += ".";
            }
            System.out.println("getAddress() + 256 :" + result);
            System.out.println();
        }
        catch(UnknownHostException e){
            e.printStackTrace();    
        }

        try{
            ip = InetAddress.getLocalHost();
            System.out.println("getHostName() :" + ip.getHostName());
            System.out.println("getHostAddress() :" + ip.getHostAddress());
            System.out.println();
        }
        catch(UnknownHostException e){
            e.printStackTrace();    
        }

        try{
            ipArr = InetAddress.getAllByName("www.daum.net");

            for (int i=0; i < ipArr.length; i++) {
                System.out.println("ipArr["+i+"]" + ipArr[i]);
            }
        }
        catch(UnknownHostException e){
            e.printStackTrace();    
        }

    }
}
getHostName() :www.daum.net
getHostAddress() :117.52.2.25
toString() :www.daum.net/117.52.2.25
getAddress() :[117, 52, 2, 25]
getAddress() + 256 :117.52.2.25.

getHostName() :KyleYui-MacBook-Pro.local
getHostAddress() :192.168.99.1

ipArr[0]www.daum.net/117.52.2.25
ipArr[1]www.daum.net/61.111.62.165

1.4 URL(Uniform Resource Location)

  • URL은 인터넷에 존재하는 여러 서버들이 제공하는 자원에 접근할 수 있는 주소를 표현하기 위한것
  • '프로토콜//호스트명:포트번호/경로명/파일명?쿼리스트링#참조' 형태로 이루어져 있다
http://www.codechobo.com:80/sample/hello.html?referer=codechobo#index1
프로토콜 자원에 접근하기 위해 서버와 통신하는데 사용되는 통신규약(http)
호스트명 자원을 제공하는 서버의 이름(www.javachobo.com)
포트번호 통신에 사용되는 서버의 포트번호(80)
경로명 접근하려는 자원이 저장된 서버상의 위치(/sample)
파일명 접근하려는 자원의 이름(hello.html)
쿼리query) URL에서 '?'이후의 부분(referer=javachobo)
참조(anchor) URL에서 '#'이후의 부분(index1)
import java.net.URL;

public class Main {

    public static void main(String[] args) {
        try {
            URL url = new URL("http://media.daum.net/mainnews/?type=sports#index1");

            System.out.println("url.getAuthority() :" + url.getAuthority());
            System.out.println("url.getContent() :" + url.getContent().toString());
            System.out.println("url.getDefaultPort() :" + url.getDefaultPort());
            System.out.println("url.getPort() :" + url.getPort());
            System.out.println("url.getFile() :" + url.getFile());
            System.out.println("url.getHost() :" + url.getHost());
            System.out.println("url.getPath() :" + url.getPath());
            System.out.println("url.getProtocol() :" + url.getProtocol());
            System.out.println("url.getQuery() :" + url.getQuery());
            System.out.println("url.getRef() :" + url.getRef());
            System.out.println("url.getUserInfo() :" + url.getUserInfo());
            System.out.println("url.toExternalForm() :" + url.toExternalForm());
            System.out.println("url.toURI() :" + url.toURI());


        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
url.getAuthority() :media.daum.net
url.getContent() :sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5e2de80c
url.getDefaultPort() :80
url.getPort() :-1
url.getFile() :/mainnews/?type=sports
url.getHost() :media.daum.net
url.getPath() :/mainnews/
url.getProtocol() :http
url.getQuery() :type=sports
url.getRef() :index1
url.getUserInfo() :null
url.toExternalForm() :http://media.daum.net/mainnews/?type=sports#index1
url.toURI() :http://media.daum.net/mainnews/?type=sports#index1

1.5 URLConnection

  • URLConnection은 어플리케이션과 URL간의 통신연결을 나타내는 클래스의 최상위 클래스로 추상클래스이다.
  • URLConnection을 상속받아 구현한 클래스로는 HttpURLConnection과 JarURLConnection이 있으며 URL의 프로토콜이 http프로토콜이라면 openConnection()은 Http URLConnection을 반환한다.
  • https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class Main {

    public static void main(String[] args) {
        URL url = null;
        BufferedReader input = null;
        String address = "http://www.codechobo.com";
        String line = "";
        try {
            url = new URL(address);
            input = new BufferedReader(new InputStreamReader(url.openStream()));

            while ((line = input.readLine()) != null){
                System.out.println(line);
            }
            input.close();

        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv='refresh' content='0;url=http://www.codechobo.com/main'>
  <title>코드초보</title>
</head>
<body>
</body>
</html>
  • 데이터가 문자데이터 이기 때문에 BefferedReader를 사용함
  • url.openStream()은 url.openConnectino().getInputStream() 과 같다
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

public class Main {

    public static void main(String[] args) {
        URL url = null;
        InputStream in = null;
        FileOutputStream out = null;
        String address = "http://www.codechobo.com";
        int ch = 0;
        try {
            url = new URL(address);
            in = url.openStream();
            out = new FileOutputStream("javajungsuk.zip");

            while( (ch=in.read()) != -1){
                out.write(ch);
            }
            in.close();
            out.close();

        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
Helloworld.class        Helloworld.java         Java                    Test.iml                javajungsuk.zip         out                     src
  • 텍스트가 아닌 이진 데이터를 읽어서 파일에 저장하는 예제

2. 소켓 프로그래밍

  • 소켓(socket)
    • 네트워크의 양방향 통신에서 양쪽 끝단으로, TCP/IP 단에서 구분할 수 있는 하나의 포트 번호를 가진다.
  • Java의 소켓 프로그래밍
    • java.net 패키지가 소켓 프로그래밍 클래스들을 제공한다.

2.1 TCP와 UDP

  • TCP/UDP
    • TCP와 UDP 모두 TCP/IP 프로토콜에 포함되어있는 프로토콜로, OSI 7계층의 전송 계층(transport layer)에 해당하는 프로토콜이다.
  • TCP와 UDP의 특징
항목 TCP UDP
연결방식 연결 기반, 1:1 통신 비연결기반, 1:1 / 1:n / n:n 통신
특징 바이트 단위로 전송, 신뢰성 기반: 전송 순서 보존 / 수신 여부 확인 데이터 단위로 전송, 신뢰성이 없다
클래스 Socket, ServerSocket DatagramSocket, DatagramPacket, MulticastSocket

2.2 TCP소켓 프로그래밍

  • 서버/클라이언트의 통신 과정
    1. [서버] ServerSocket으로 특정 포트로 소켓을 연다.
    2. [클라이언트] 서버의 IP 주소와 포트로 Socket으로 소켓을 만들어 서버에 연결 요청을 한다.
    3. [서버] 클라이언트의 연결 요청을 받으면 Socket으로 소켓을 만들어 클라이언트의 소켓과 연결한다.
    4. [서버/클라이언트] 연결된 각자의 소켓을 이용해 통신을 한다.
  • 소켓
    • 여러 소켓이 포트 하나를 공유할 수 있지만, 서버소켓은 포트 하나를 독점한다.
    • 소켓은 입력스트림과 출력스트림을 가지고 상대방 소켓과 서로 교차연결해 데이터를 주고받는다.
  • 서버 예제

    • 쓰레드로 통신하기
      class Sender extends Thread {
        DataOutputStream out;
        ...
        Sender(Socket socket) {
          ...
          out = new DataOutputStream(socket.getOutputStream());
          ...
        }
        public void run() {
          ...
          out.writeUTF("Sender message.");
          ...
        }
      }
      
      class Receiver extends Thread {
        DataInputStream in;
        ...
        Receiver(Socket socket) {
          ...
          in = new DataInputStream(socket.getInputStream());
          ...
        }
        public void run() {
          ...
          System.out.println(in.readUTF());
          ...
        }
      }
      
    • 서버

      ServerSocket serverSocket = new ServerSocket(7777);
      
      Socket socket = serverSocket.accept(); // 클라이언트의 연결 요청을 받아 통신용 소켓을 만든다.
      
      Sender sender = new Sender(socket);
      Receiver receiver = new Receiver(socket);
      
      sender.start();
      receiver.start();
      
    • 클라이언트

      Socket socket = new Socket("127.0.0.1", 7777);
      
      Sender sender = new Sender(socket);
      Receiver receiver = new Receiver(socket);
      
      sender.start();
      receiver.start();
      

2.3 UDP소켓 프로그래밍

  • 특징
    • 연결지향이 아니므로 ServerSocket이 따로 필요하지 않다.
    • 소켓은 DatagramSocket를 사용해 만들어 DatagramPacket에 데이터를 담아 통신한다.
    • DatagramPacket에는 헤더와 데이터가 있으며 헤더에 수신할 상대방의 정보(주소와 포트)를 저장한다.
  • 예제

    • 서버

      DatagramSocket datagramSocket = new DatagramSocket(7777);
      
      byte[] inMsg = new byte[10];
      // (데이터, 데이터 길이) - 받을 패킷 만들기
      DatagramPacket inPacket = new DatagramPacket(inMsg, inMsg.length);
      
      socket.receive(inPacket);
      
      System.out.println(new String(inPacket.getData());
      
      dataSocket.close();
      
    • 클라이언트

      // 클라이언트는 포트를 지정하지 않는다.
      DatagramSocket datagramSocket = new DatagramSocket();
      
      InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
      byte[] msg = new byte[10];
      // (데이터, 데이터 길이, 주소, 포트) - 보낼 패킷 만들기
      DatagramPacket outPacket = new DatagramPacket(msg, msg.length, serverAddress, 7777);
      
      datagramSocket.send(outPacket);
      
      datagramSocket.close();