Network는 다양한 컴퓨터들끼리 연결되어 있는 망을 의미한다.


컴퓨터 뿐만 아니라 다양한 사물(Things), 예를들어 냉장고 선풍기, 에어컨 등의 사물(Things)들이 Network, Internet에 연결이 되고


그것을 IOT(Internet Of Things) 사물 인터넷이라고 한다.


특히 Java는 컴퓨터를 벗어나 다양한 사물에 활용되기 좋아 널리 사용되고 있다.







Network의 깊은 지식이 목적이 아니기 때문에 전문적인 내용을 다루지 않고


Java에서 쓸만한 간단한 Server, Client 통신을 공부한다.







Network는 결국 목적지까지 어떻게 가느냐가 제일 중요한 과제이다.


그래서 컴퓨터에 고유 통신 번호인 IP가 지정되고 IP는 집주소 처럼 데이터를 전달할 목적지 주소로 쓰이게 된다.


또한 컴퓨터 장치 자체에 부여된 주소도 따로 있지만 IP만 사용한다.


IP와 함께 필요한게 하나 있는데 포트 번호가 꼭 필요하다.


일반적으로 사용하는 포트는 TCP와 UDP가 있고


TCP는 Three Way Handshake와 같은 방법으로 확실한 데이터를 전송하지만 속도가 조금 느리다.


UDP는 일방적인 전송을 하므로 불확실한 데이터를 전송하지만 속도가 빠르다는 장점이 있다.







IP와 포트의 예로는 127.0.0.1:8080과 같이


127.0.0.1은 IP가 되고


: 뒤에 8080은 포트 번호가 된다.


그리고 127.0.0.1은 자신을 지정하는 IP로 자신의 IP를 모를때 쓰는 IP이다.





Java에서 자신의 IP 주소를 얻는법과


특정 도메인의 IP를 얻는법을 확인해보자


InetAddress를 사용한다.





여기서 도메인은 네이버로 예를 든다면


naver.com이 도메인(IP의 닉네임으로 이해하면 된다)이다.


수많은 웹사이트들을 접속하는데 일일히 IP를 암기하고 사용 할 수 없으니 닉네임을 배정하는 혁신적인 기술이다.


도메인이 생기고 인터넷의 발전은 급격히 상승했다.



package chap12.exam01.ipaddr;

import java.net.InetAddress;

public class GetIp {

	public static void main(String[] args) throws Exception {
		// 내 컴퓨터의 IP 얻기
		// localhost => 127.0.0.1 => 자신의 주소를 지정하는 주소
		InetAddress addr = InetAddress.getLocalHost();
		System.out.println("my PC IP " + addr.getHostAddress());
		
		// 특정 도메인으로 IP 얻기
		String domain = "naver.com";
		addr = InetAddress.getByName(domain);
		System.out.println(addr.getHostAddress());
		
		// 특정 도메인으로 IP 전부 얻기
		domain = "www.youtube.com";
		InetAddress[] addrs = InetAddress.getAllByName(domain); // 반환값이 배열
		for(InetAddress ip : addrs) {
			System.out.println("ip : " + ip);
		}
	}

}



여기서 특정 도메인으로 IP 전부 얻기라는 말이 이해가 안 갈수도 있다.


왜 여러대가 나오는거지? 할 수 있는데 웹사이트들은 서버를 여러대를 두어 접속을 대비하여야 하기 때문에 여러개가 나온다.


예를들면 naver.com과 같이 대형 웹사이트는 1분안에 수만, 수십만명이 동시에 접속할 수 있기 때문에


서버를 여러대 준비하여 부하가 낮아지게끔 해야한다.


만약 여러대를 준비하지 않을 경우 사람이 몰리는 아침시간에 naver.com에 접속하려고 하면


과장해서 1시간, 2시간 걸릴 것이다...



'개념 및 코딩 > 10.네트워크' 카테고리의 다른 글

[JAVA]10-06.UDP, Datagram  (0) 2018.09.27
[JAVA]10-05.N:M MultiChat Server, Client  (2) 2018.09.27
[JAVA]10-04.1:1 Chat Server, Client  (0) 2018.09.27
[JAVA]10-03.Echo Server, Client  (0) 2018.09.27
[JAVA]10-02.TCP Server, Client  (0) 2018.09.27

Java NIO는 New Input Output의 줄임말로 기능 중 간단한 파일 제어만 설명


Java IO와는 다르게 Stream이 아니고 Channel 방식을 사용




1. Files, 파일 다루기


Files의 다양한 메소드들은 다음 예제를 통해 확인하자.



package chap11.exam13.files;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FilesExam {
	// 파일의 속성을 알아 볼 수 있다.
	public static void main(String[] args) throws Exception {
		
		Path path = Paths.get("C:/img/asd.txt");
		System.out.println("디렉토리 여부 : " + Files.isDirectory(path));
		System.out.println("파일 여부 : " + Files.isRegularFile(path));
		System.out.println("마지막 수정 시간 : " + Files.getLastModifiedTime(path));
		System.out.println("파일 크기 : " + Files.size(path));
		System.out.println("소유자 : " + Files.getOwner(path));
		System.out.println("숨김 파일 여부 : " + Files.isHidden(path));
		System.out.println("읽기 가능 여부 : " + Files.isReadable(path));
		System.out.println("쓰기 가능 여부 : " + Files.isWritable(path));
		System.out.println("실행 여부 : " + Files.isExecutable(path));
	}

}



2. FileSystem, 파일 정보


FileSystem은 현재 시스템의 다양한 정보를 불러올 수 있다.


Iterable에 FileStroe을 붙여서 사용



package chap11.exam13.files;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;

public class FileSystemExam {
	// 파일 시스템(파일/폴더/저장공간) 정보
	public static void main(String[] args) throws IOException {
		// 기본 파일 시스템 정보 추출하는 객체
		FileSystem fs = FileSystems.getDefault();
		Iterable<FileStore> infolist = fs.getFileStores();
		for(FileStore info : infolist) {
			System.out.println("드라이브 이름 : " + info.name());
			System.out.println("저장 타입 : " + info.type());
			System.out.println("용량 : " + info.getTotalSpace()/(1024*1024*1024) + "GB");
			System.out.println("사용 가능한 용량 : " + info.getUsableSpace()/(1024*1024*1024) + "GB");
		}
		
		System.out.println("====현재 사용중인 드라이버 루트 ====");
		for(Path path : fs.getRootDirectories()) {
			System.out.println(path.toString());
		}
	}

}



3. Path, 경로


Path는 경로에 관련된 다양한 메소드들이 있다.


폴더 생성 또는 파일 이름만 뽑는다던가 상위 폴더를 알아 낸다던가 등 여러가지 있다.



package chap11.exam13.files;

import java.nio.file.Path;
import java.nio.file.Paths;

public class PathExam {
	// 1. 파일 경로 확인 전문화
	public static void main(String[] args) {
		// 특정 경로의 파일 정보를 가져옴(Uri | String)
		Path path = Paths.get("C:/img/temp/10multi_copy");
		
		// 파일명
		System.out.println(path.getFileName());
		// 부모 확인
		System.out.println(path.getParent().getFileName());
		// 루트 확인
		System.out.println(path.getRoot());
		// 위에 쓴 경로들의 단계 수
		System.out.println(path.getNameCount());
		// 개별 단계 확인
		for(int i = 0; i < path.getNameCount(); i++) {
			System.out.println(i + " 단계 : " + path.getName(i));
		}
	}

}



package chap11.exam13.files;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class MKdirExam {
	// 디렉토리 및 파일 생성
	public static void main(String[] args) throws Exception {
		Path path = Paths.get("c:/img/test");
		// !File.exists()
		if(Files.notExists(path)) {
			System.out.println("폴더 생성");
			Files.createDirectories(path);
		}
		path = Paths.get("c:/img/test/textFile.txt");
		if(Files.notExists(path)) {
			System.out.println("파일 생성");
			Files.createFile(path);
		}
	}

}




4. WatchService, 파일 감시


WatchService는 지정한 폴더 내부의 파일이 생성되거나 수정되거나 삭제되는 경우를 감지하는 기능을 가지고 있다.


생성 시 감시할 이벤트들을 설정하고 사용한다.



package chap11.exam13.files;

import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;

public class WatchServiceExam {
	// 특정 경로의 파일 변경을 감시
	public static void main(String[] args) throws Exception {
		
		// 기본 영역 지정
		WatchService watch = FileSystems.getDefault().newWatchService();
		
		// 감시 할 상세 주소 지정
		Path path = Paths.get("c:/img");
		
		// 어떤 와치 서비스가 어떤것을 감시하나?
		path.register(watch,  StandardWatchEventKinds.ENTRY_CREATE, 
				StandardWatchEventKinds.ENTRY_DELETE, 
				StandardWatchEventKinds.ENTRY_MODIFY);
		// 감시 실행
		while(true) {
			// 등록한 이벤트 발생 시 WatchKey로 반환
			WatchKey key = watch.take();
			// 이벤트 추출, ?는 와일드 카드 타입
			List<WatchEvent<?>> list = key.pollEvents();
			// 상세 내용을 추출
			for(WatchEvent e: list) {
				// 이벤트 상세 내용
				Kind evtKind = e.kind();
				Path evtPath = (Path) e.context();
				System.out.println(evtKind);
				System.out.println(evtPath);
			}
			// 다 쓰고난 이벤트 키는 리셋 해 주어야 한다.
			// reset을 하지 않으면 감시가 일회성으로 끝난다.
			// false : 초기화 실패, 해당 디렉토리가 사라진 경우
			boolean success = key.reset();
			System.out.println(success);
		}
	}

}



5. Path를 이용한 Write Read Copy


위에 사용한 Path를 이용하여 파일을 만들거나 읽거나 복사하는 기능


쓰기


package chap11.exam14.fileRW;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Scanner;

public class fileWriteEx {

	public static void main(String[] args) throws Exception{
		// 파일 위치 지정
		Path path = Paths.get("c:/img/write.txt");
		// 쓰기 할 값 입력 받기
		Scanner scan = new Scanner(System.in);
		System.out.println("아무거나 입력하세요!");
		String txt = scan.nextLine() + "\r\n";
		// 스트림 준비 + 쓰기
		Files.write(path, txt.getBytes(), StandardOpenOption.APPEND);
		System.out.println("저장 되었습니다.");
		// 자원반납(flush, close) - 생략
	}

}


읽기


package chap11.exam14.fileRW;

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class FileReadEx {

	public static void main(String[] args) throws Exception {
		// 1. 경로
		Path path = Paths.get("C:/img/asd.txt");
		// 2. 스트림 생성		// 3. 읽기
		List<String> contents = Files.readAllLines(path, Charset.forName("UTF-8"));

		// 4. 출력
		for(String line : contents) {
			System.out.println(line);
		}
	}

}


복사


package chap11.exam14.fileRW;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopyEx {
	// 파일 복사
	public static void main(String[] args) throws Exception {
		// 읽어와서 -> 쓰기
		// 파일 지정
		Path from = Paths.get("c:/img/10multi.pdf");
		Path to = Paths.get("c:/img/temp/10multicopyFile");
		// 스트림 + 읽기 + 읽어온 값 쓰기
		Files.copy(from,  to, StandardCopyOption.REPLACE_EXISTING);
		System.out.println("파일 복사 완료");
		// REPLACE_EXISTING : 기존 파일이 있으면 덮어쓰기
		// COPY_ATTRIBUTES : 파일의 모든 속성 복사(권한, 읽기 전용)
		// 자원 반납
	}

}


Data Stream은 .dat 파일을 만들 때 사용하는 스트림으로 


특징은 dat 파일을 읽기 위해서는 어떤 타입이 어떤 순서로 들어있는지 알아야 읽을 수 있기 때문에


쉽게 읽어올 수 없다는 특징을 가진다.



package chap11.exam10.data;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class DataOutput {

	public static void main(String[] args) throws Exception {
		// 자료형을 유지해서 파일에 쓰기
		// 1. 파일 위치 설정
		String path = "C:/img/data.dat";
		// 2. 스트림 준비(보조)
		FileOutputStream fos = new FileOutputStream(path);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		DataOutputStream dos = new DataOutputStream(bos);
		
		// 3. 쓰기
		dos.writeUTF("aaa");
		dos.writeInt(1000);
		dos.writeBoolean(true);
		
		// 4. 비우기
		dos.flush();
		
		// 5. 닫기
		dos.close();
		bos.close();
		fos.close();
	}

}


package chap11.exam10.data;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;

public class DataInput {

	public static void main(String[] args) throws Exception {
		
		// 1. 파일 위치 설정
		String path = "C:/img/data.dat";
		// 2. 스트림 준비(보조)
		FileInputStream fis = new FileInputStream(path);
		BufferedInputStream bis = new BufferedInputStream(fis);
		DataInputStream dis = new DataInputStream(bis);
		
		// 3. 읽기 (파일에 있는 타입들을 알아야 하고
		// 입력한 순서대로 불러야 한다.)
		// 4. 출력
		System.out.println("이름 : " + dis.readUTF());
		System.out.println("급여 : " + dis.readInt());
		System.out.println("승진대상 : " + dis.readBoolean());
		
		
		
		// 5. 닫기
		dis.close();
		bis.close();
		fis.close();
	}

}



다양한 스트림들은 다양한 타입을 다루기에는 적절하지 않고 보통 하나에 특화 되어 있다.


그러나 Object Stream은 데이터 타입의 최상위 객체인 Object를 의미하는 보조 스트림으로


다양한 데이터 타입 뿐만 아니라 객체, 배열, 컬렉션 등 다양한 형태가 들어 갈 수 있다.


하지만 클래스의 경우는 직렬화를 하지 않으면 전달되지 않는다.


직렬화는 전달 할 데이터를 바이트로 바꿔서 나열하는 것이다.


다음 예제는 dat 파일을 만들어 읽는데 Sample이라는 클래스도 함께 전달하는 예제이다.



package chap11.exam11.obj;

import java.io.Serializable;
// 직렬화 인터페이스를 통해 모양을 잡아 준다.
public class Sample implements Serializable {
	/**
	 * 통신 시 사용하는 일련번호 serialVersionUID
	 * 객체 통신을 위한 일련번호
	 */
	private static final long serialVersionUID = 1L;
	int num = 11;
	String team = "edu";
	String job = "manager";
	
	public String method() {
		return "메소드 호출";
	}
}



package chap11.exam11.obj;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

public class ObjOutput {

	public static void main(String[] args) throws Exception {
		// 1. 파일 위치 설정
		String path = "C:/img/temp/obj.dat";
		// 2. 스트림 준비(보조)
		FileOutputStream fos = new FileOutputStream(path);
		DataOutputStream dos = new DataOutputStream(fos);
		ObjectOutputStream oos = new ObjectOutputStream(dos);
		// 3. 쓰기
		// - Map으로
		Map<String, String> map = new HashMap<>();
		map.put("name",  "kim");
		map.put("phone", "010-1234-5678");
		oos.writeObject(map);
		// - Array로
		oos.writeObject(new int[] {90, 95, 90, 100});
		// - String으로
		oos.writeUTF("기본형도 가능");
		// - Instance Object, 객체화하여 넣기
		oos.writeObject(new Sample());
		// 4. 비우기
		oos.flush();
		// 5. 자원 반납
		oos.close();
		dos.close();
		fos.close();
	}

}



package chap11.exam11.obj;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Map;
import java.util.Set;

public class ObjInput {

	public static void main(String[] args) throws Exception {
		// 1. 경로 설정
		String path = "C:/img/temp/obj.dat";
		
		// 2. 스트림 생성
		FileInputStream fis = new FileInputStream(path);
		BufferedInputStream bis = new BufferedInputStream(fis);
		ObjectInputStream ois = new ObjectInputStream(bis);
		
		// 3. 읽기 
		Map<String, String> map = (Map<String, String>)ois.readObject();
		int [] scores = (int[])ois.readObject();
		String msg = (String)ois.readUTF();
		Sample sample = (Sample)ois.readObject();
		
		// 4. 출력하기
		Set<String> set = map.keySet();
		for(String key : set) {
			System.out.println(key + " : " + map.get(key));
		}
		
		for(int i = 0; i < scores.length; i++) { System.out.println(scores[i]); }
		
		System.out.println(msg);
		
		System.out.println("sample : " + sample.num);
		System.out.println("sample : " + sample.job);
		System.out.println("sample : " + sample.team);
		System.out.println("sample : " + sample.method());
		
		// 4. 해제
		ois.close();
		bis.close();
		fis.close();
	}

}





Prop은 Properties의 줄임말로 보통 Java Project 내부에서 읽고 쓰기를 한다.


프로그램의 내부에서 사용하기 때문에 환경 설정, 저장한 데이터 등의 데이터를 저장한다.


Properties는 map 인터페이스를 상속받은 자료 구조이다.


다음 예제를 확인해보자. 예제를 실행 하면 클래스 파일 옆에 Properties 파일이 생성된다.



package chap11.exam12.prop;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.Properties;

public class PropWriter {

	public static void main(String[] args) throws Exception {
		// 1. 파일 위치 지정
		String path = "src/chap11/exam12/prop/profile.properties";
		
		// 2. Properties 객체 준비
		Properties pro = new Properties();
		
		// 3. 객체에 값 추가 (무엇을 넣어도 문자열로 넣어버림
		pro.put("1", "1111");
		pro.put("2", "2222");
		pro.put("3", "3333");
		pro.put("4", "4444");
		pro.put("5", "5555");
		
		// 4. 스트림 준비
		FileOutputStream fos = new FileOutputStream(path);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		// 5. 저장(스트림, 주석)
		pro.store(bos, "simple Comment");
		System.out.println("저장 완료");
		
		// 6. 자원 반납
		bos.close();
		fos.close();
	
	}

}



package chap11.exam12.prop;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class PropReader {

	public static void main(String[] args) throws Exception {
		// 1. 불러올 파일 위치 지정
		String path = "";
		// jar로 배포하고나면 사용자마다 경로가 상이하므로
		// 특정 클래스를 기준으로 리소스를 호출해야 한다.
		// 1-1. 경로를 가져오는 방법
//		path = PropReader.class.getResource("profile.properties").getPath();
//		System.out.println(path);
		// 1-2. 스트림으로 직접 불러오는 방
		InputStream is = PropReader.class.getResourceAsStream("profile.properties");
		
		// 2. 프로퍼티 객체 준비
		Properties pro = new Properties();
		
		// 3. 스트림 준비
		BufferedInputStream bis = new BufferedInputStream(is);
		
		// 4. 읽어오기
		pro.load(bis);
		
		// 5. 객체에서 값을 하나씩 추출
		System.out.println(pro.get("1"));
		System.out.println(pro.get("2"));
		System.out.println(pro.get("3"));
		System.out.println(pro.get("4"));
		System.out.println(pro.get("5"));
		
		// 6. 자원 반납
		bis.close();
		is.close();
		
		// 간단한 설정에 좋음, 보안성이 안좋음(전부 String)
		
	}

}



+ Recent posts