JAVA 웹개발 과정 국비 27일차 정리

27일차

※ 배우는 과정이므로 정확하지 않을 수 있습니다.
잘못된 점은 알려주시면 수정하도록 하겠습니다!


네트워크를 가볍게 알아보는 시간을 가졌다.

1. 네트워크 프로그래밍

지금까지 만든 프로그램들을 사용하려면 내 PC에서만 가능했었는데, 서버로 프로그램을 옮겨서 다른 PC에서도 접근이 가능하도록 만들려면 network에 대해서 알아야 한다.
서버 - 클라이언트 네트워크 통신 프로그램으로 1 : N 관계에서 사용 가능하게 만들어보자.

1) 용어 정리

  • 서버
    • 특정 서비스(ex)네이버, 카카오톡)를 제공하는 프로그램 또는 장치 (PC 또는 전용장치)
  • 클라이언트
    • 제공되는 서비스를 이용하는 고객들
  • IP 주소
    • 인터넷 상에서 PC를 구분짓는 고유 식별 ID로 사용되는 주소
    • 4바이트 주소 체계 $2^{32}$
  • 포트번호
    • IP 주소로 식별된 PC 내에서 서비스를 구분짓는 고유 번호
    • 1 ~ 65535번 중에 설정 (1 ~ 1024번까지는 Well Known 이다.)
  • 스트림
    • 네트워크에서만 쓰이는 언어는 아니다. 데이터를 주고 받는 통로를 일컫는다.
  • 공유기(Gateway)
    • 전 세계 모든 장비에 IP를 할당하기에는 기존 IP 값이 부족하기 때문에 사용하게 됨.
    • 사설 네트워크를 만들면서 동시에 공인 아이피를 하나 가진다.
    • 인터넷이 굳이 필요하지 않은 개인 인터넷 등을 사설 네트워크로 만들어 인터넷을 사용할 때는 공인 IP로 바꾸어 사용할 수 있다.
  • 사설IP(사설대역대)
    • 인터넷을 사용하지 않는 IP.
    • 192.168~ 또는 172.16~ 을 사용한다.
  • 포트포워딩
    • 사설 네트워크에 있는 PC를 서버로 이용할 때 공인 IP가 필요한데 공유기의 공인IP를 이용하면 서버로 사용할 PC까지 도달하지 못한다. 이 때 공인 IP로 들어오는 특정 포트의 연결을 사설 네트워크에 있는 서버로 사용할 PC의 특정 포트로 연결하라고 공유기에게 알려주어야 한다. 이 설정을 포트포워딩이라고 한다.
  • 소켓
    • 네트워크 프로그램에서 통신을 수행하기 위한 논리적 단말기
    • 네트워크 통신을 전화로 비유하면 소켓은 가상의 전화기이다.
    • 서버는 서버소켓을 가지게 되는데, 일반 전화가 아닌 전화교환원(소켓공장)을 가지고 있다고 생각하면 된다.

2) 간단한 네트워크 프로그램 만들기

아직 완전한 프로그램이 아니므로 일시적으로 main에 throws Exception을 해준다.

① Server 클래스

public class Server {
	public static void main(String[] args) throws Exception {
	
	}
}
ⓐ 소켓 만들기

ServerSocket 객체를 생성하여 서버 소켓을 만들어준다.
파라미터로는 포트번호를 가지는데 임시로 22000으로 설정해주었다.

ServerSocket server = new ServerSocket(22000);
ⓑ 접속 대기
  • ServerSocket.accept() : Socket
    • accept 메소드는 누군가가 접속을 하면 실행이 된다. 예를 들면 nextLine()과 같은 역할이라고 생각하면 된다.
    • 클라이언트가 접속할때까지 대기하는 상태이다.
    • 리턴 값으로 Socket을 가진다.
  • Socket.getInetAddress() : InetAddress
    • 서버로 접속한 클라이언트의 IP주소를 리턴한다.
Socket sock = server.accept();
System.out.println(sock.getInetAddress() + "로부터 연결되었습니다.");
ⓒ 스트림 개방

데이터를 주고 받기 위한 통로를 개방하는 코드이다.
서버와 클라이언트 각각 반쪽씩의 통로를 가지고 있다.
InputStream과 OutputStream은 밧줄로 연결되어 있는 통로라고 생각하면 되는데 아주 약해서 돌다리로 업데이트를 해줘야 한다. 그것이 DataInputStream 과 DataOutputStream 이다.

  • Socket.getInputStream() : InputStream
    • 데이터를 받아들이는 통로를 열겠다 선언!
    • 밧줄로 된 데이터 받는 통로
  • Socket.getOutputStream() : OutputStream
    • 데이터를 보내는 통로를 열겠다 선언!
    • 밧줄로 된 데이터 보내는 통로
  • DataInputStream(InputStream)
    • 생성자로 InputStream을 받는 DataInputStream 객체 생성
    • 밧줄을 돌다리로 튼튼하게 만들어준다.
  • DataOutputStream(OutputStream)
    • 생성자로 OutputStream을 받는 DataOutputStream 객체 생성
    • 밧줄을 돌다리로 튼튼하게 만들어준다.
InputStream is = sock.getInputStream();
DataInputStream dis = new DataInputStream(is);

OutputStream os = sock.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
ⓓ 데이터 받기

상황에 따라 while문으로 메세지 주고 받기를 계속 진행 할 수 있다.

  • DataInputStream.readUTF() : String
    • 클라이언트가 보낸 메세지(문자열)를 리턴한다.
    • readInt(), readBoolean() 등 다른 자료형을 받는 메소드들도 있다.
String msg = dis.readUTF();
System.out.println("클라이언트가 보낸 메세지 : " + msg);

② Client 클래스

Server와 마찬가지로 throws Exception을 해준다.

public class Client {
	public static void main(String[] args) throws Exception {
	
	}
}
ⓐ 소켓 만들기

서버와는 달리 Socket 객체를 만든다.
파라미터는 접속할 ip 주소와 포트번호를 적어준다.
일단은 localhost ip주소인 127.0.0.1 을 적었다.

Socket client = new Socket("127.0.0.1", 22000);
ⓑ 스트림 개방

데이터를 내보낼 때는 write라는 명령을 쓰는데 wirte 메소드를 쓰려고 보니 byte나 int값밖에 파라미터로 사용하지 못한다.
통로는 개방이 되었는데, 밧줄하나 정도의 튼튼하지 못한 다리여서 문자열같이 큰 데이터를 전달하기가 불편한 것이다.
위에서 언급했듯이 이 다리를 쓰기 편하게 즉, 밧줄을 돌다리로 업그레이드 시키는데 그것이 DataOutputStream이다.

데이터를 받는 InputStream도 개념이 동일하다.

OutputStream os = client.getOutputStream();
DataOutputStream dis = new DataOutputStream(os);

InputStream is = client.getInputStream();
DataInputStream dis = new DataInputStrea(is);
ⓒ 데이터 내보내기
  • DataOutputStream.writeUTF(String) : void
    • 데이터를 보내는 메소드가 아닌, 데이터를 담는 택배차량에 싣겠다라는 메소드
    • 서버에게 보내고 싶은 문자열을 입력하면 된다.
    • 택배차가 꽉 찼을 때, 어떤 자동적인 상황일 때, flush를 만났을 때 택배차는 출발한다.
  • DataOutputStream.flush() : void
    • 택배차를 출발시키는 메소드.
  • JOptionPane.showInputDialog(Object message) : String
    • 사용자 입력창을 그래픽 화면으로 띄워주는 메소드.
    • String (입력값) 을 반환한다.
dos.writeUTF(JOptionPane.showInputDialog("메세지를 입력하세요."));
dos.flush();

3. time 입력하면 시간을 출력하는 프로그램 - 예제

클라이언트가 time을 입력하면 서버에서 현재 시간을 보여주는 프로그램을 만들어보자.

// Server Class
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;

public class Server {
	public static void main(String[] args) throws Exception{
		ServerSocket server = new ServerSocket(20000);
		
		System.out.println("연결을 대기하는 중입니다..");
		Socket sock = server.accept();
		
		DataInputStream dis = new DataInputStream(sock.getInputStream());
		DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 hh:mm:ss");
		
		String msg = dis.readUTF();
		if(msg.equals("time")) {
			long timestamp = System.currentTimeMillis();
			String dateString = sdf.format(timestamp);
			dos.writeUTF(dateString);
			dos.flush();
		}
		
	}
}
// Client Class
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import javax.swing.JOptionPane;

public class Client {
	public static void main(String[] agrs) throws Exception {		
		
		Socket client = new Socket("127.0.0.1", 20000);
		
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		DataInputStream dis = new DataInputStream(client.getInputStream());
		
		String msg = JOptionPane.showInputDialog("명령어를 입력하세요.");
		dos.writeUTF(msg);
		dos.flush();
		
		String dateString = dis.readUTF();
		System.out.println("현재 시간 : " + dateString);
	}
}

댓글남기기