본문 바로가기

회고록(TIL&WIL)

WIL 2023.01.05 ~ 2023.01.06 통신, 네트워크

통신

IP

원격으로 pc에 접속하기 위해선 ip가 필요하다 ip는 (1byte x 4)의 체계를 갖추고 있다.
ip는 0~255까지 정수 4자리로 이루어져 있다. ipv6은 주소로 16진수 4자리수 ipv9도 있긴한데 중국에서만 사용한다.
공인IP - 진짜IP 인터넷에서 사용자 식별을 위한 IP
사설IP - 공유기에 묶여서 등장하는 IP와 같이 별도의 네트워크에서 사용되는 IP, 외부에서 접근은 불가능하며 중복이 가능하다.
유동IP
개인사용자를 위해서 임의의 비어있는 ip를 받아 사용하는 것 가정에서는 사설IP면서 유동IP 인 것
자동으로 게이트웨이, 서브넷마스크, DNS를 자동할당 해줘서 인터넷과 연결하기 쉽도록 해주는게 DHCP 서버이다.
일반적으로 공유기가 해당 기능을 수행해줌
고정IP
학교,회사 등 관공서에서는 DHCP를 지원하지 않기 때문에 직접 설정을 해줘야 인터넷을 사용 할 수 있게 된다.
게이트웨이, DNS, 서브넷 마스크를 직접 기입 해줘야 인터넷을 사용 할 수 있다.
또한 변경되어서도 안되기 때문에 고정 IP를 이용해야한다.

DNS - Domain Name Server

원칙은 ip를 통해서 접속해야하는 것이 맞으나 전부 기억할 수 없기에
Domain을 지정해서 naver.com와 같은 값을 입력하여 해당 pc에 접속 할 수 있도록 함.
naver.com을 입력하는 순간 DNS에 해당 이름을 찾아 달라고 요청하는데
그러면 DNS에서 ip를 알려주고 우리는 받은 ip를 통해 네이버에 접속할 수 있게 되는 것
DNS서버의 주소는 통신사를 무엇을 사용하느냐에 따라 달라지게된다.

host

windows의 hosts파일에 저장되어있는 Domain과 ip가 있을 경우 DNS서버에 가서 안물어보고 바로 해당 ip로 가게 된다.
이를 이용하여 hosts 파일을 위변조하여 피싱사이트에 접속되도록 할 수 있게 된다.
그렇기에 공용으로 사용되는 컴퓨터에서 모든 내용을 100% 신뢰하기 어렵게 된다.

InetAddress

public class Ex01 {

	public static void main(String[] args) {
		java.net.InetAddress addr1 = null;
		java.net.InetAddress addr2 = null;
		java.net.InetAddress addr3 = null;
//		addr1 = new InetAddress(); // default 생성자가 없다.
		try {
			// 도메인 이름을 통한 연결
			addr1 = InetAddress.getByName("naver.com");
			System.out.println(addr1.getHostName()); // naver.com
			System.out.println(addr1.getHostAddress()); // 223.130.195.95
			
			System.out.println("======");
			
			// IP를 통한 연결 (ipv4) - (1byte x 4) 의 체계를 갖추고 있다.
			byte[] arr1 = {(byte)223,(byte)130,(byte)195,95}; // byte배열을 받음
			addr2 = InetAddress.getByAddress(arr1); 
			System.out.println(addr2.getHostAddress());
			
			System.out.println("======");
			
			// 내 ip 192.168.240.119
//			byte[] arr2 = {(byte)192,(byte)168,(byte)240,119};
			byte[] arr2 = {127,0,0,1}; // localhost
//			addr3 = InetAddress.getByAddress(arr2); 
//			addr3 = InetAddress.getByName("DESKTOP-O5AJ5VH");
			addr3 = InetAddress.getByName("localhost");
			System.out.println(addr3.getHostName()); 
			System.out.println(addr3.getHostAddress());
			
			System.out.println("======");
			 
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}

}

URL

public class Ex03 {

	public static void main(String[] args) {
		// URL vs URI
		// 프로토콜://도메인:포트번호/경로/../경로?쿼리스트링#ref(앵커)
		String msg = "";
		msg = "https://namu.wiki/w/%EB%A7%A4%EB%8B%88%20%ED%8C%8C%ED%80%B4%EC%95%84%EC%98%A4#s-8";
		java.net.URL url = null;
		try {
			url = new URL(msg);
			System.out.println("protocol : " + url.getProtocol());
			System.out.println("domain : " + url.getHost());
			System.out.println("port : " + url.getPort());
			System.out.println("default port : " + url.getDefaultPort());
			System.out.println("file : " + url.getFile());
			System.out.println("path : " + url.getPath());
			System.out.println("queryString : " + url.getQuery());
			System.out.println("ref : "+ url.getRef());
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

}

웹크롤링

public class Ex04 {

	public static void main(String[] args) {
		File file = new File("7zip.exe");
		URL url = null;
		InputStream is = null;
//		InputStreamReader isr = null;
//		BufferedReader br = null;
		
		//byte stream
		OutputStream os = null;
		
		// 문자열인 경우
//		Writer fw = null;
//		PrintWriter pw = null;
		try {
			os = new FileOutputStream(file);
//			fw = new FileWriter(file);
//			pw = new PrintWriter(fw);
			url = new URL("https://www.7-zip.org/a/7z2201-x64.exe");
			URLConnection conn = url.openConnection();
			is = conn.getInputStream();
//			isr = new InputStreamReader(is);
//			br = new BufferedReader(isr);
			
//			String msg = null;
//			while((msg=br.readLine())!=null){
//				os.(msg);
//			}
			int su = -1;
			while((su=is.read())!=-1) {
				os.write(su);
			}
			
			System.out.println("크롤링 완료");
//			if(br!=null)br.close();
//			if(isr!=null)is.close();
			if(is!=null)is.close();
			if(os!=null)os.close();
//			if(pw!=null)pw.close();
//			if(fw!=null)fw.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

소켓통신

Client

public class Client extends Frame implements ActionListener{
	TextField tf = new TextField();
	static TextArea ta = new TextArea();
	static PrintWriter pw;
	
	public Client() {
		setLayout(new BorderLayout());
		add(ta, BorderLayout.CENTER);
		add(tf, BorderLayout.SOUTH);
		tf.addActionListener(this);
		setBounds(100,100,300,400);
		setVisible(true);
	}
	@Override
	public void actionPerformed(ActionEvent e) {	
		String msg = tf.getText();
		pw.println(msg);
		pw.flush();
		tf.setText("");
	}

	public static void main(String[] args) {
		Client client = new Client();
		String url = "192.168.240.119";
		int port = 8080;
		Socket sock = null;
		InputStream is = null;
		OutputStream os = null;
		InputStreamReader isr = null;
		OutputStreamWriter osw = null;
		BufferedReader br = null;
		
		try {
			sock = new Socket(url, port);
			is = sock.getInputStream();
			os = sock.getOutputStream();
			isr = new InputStreamReader(is);
			osw = new OutputStreamWriter(os);
			br = new BufferedReader(isr);
			pw = new PrintWriter(osw);
			
			String msg = null;
			while(true) {
				msg = br.readLine(); // 계속 읽어오는데
				if(msg.equals("exit"))break;
				ta.append(msg + "\n"); // 읽어온 값을 ta에 넣어주는 것 
			}
			
			if(pw!=null)pw.close();
			if(br!=null)br.close();
			if(osw!=null)osw.close();
			if(isr!=null)isr.close();
			if(os!=null)os.close();
			if(is!=null)is.close();
			if(sock!=null)sock.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
		
	}

}

Server

public class Server {

	public static void main(String[] args) {
		List<PrintWriter> list = new ArrayList<PrintWriter>();
		ServerSocket serve = null;
		try {
			serve = new ServerSocket(8080);
			while (true) {
				final Socket sock = serve.accept();
				Thread thr = new Thread(new Runnable() {
					
					@Override
					public void run() {
						InputStream is = null;
						OutputStream os = null;
						InputStreamReader isr = null;
						OutputStreamWriter osw = null;
						BufferedReader br = null;
						PrintWriter pw = null;
						InetAddress addr = null;
						try {
							addr = sock.getInetAddress();
							is = sock.getInputStream();
							os = sock.getOutputStream();
							isr = new InputStreamReader(is);
							osw = new OutputStreamWriter(os);
							br = new BufferedReader(isr);
							pw = new PrintWriter(osw);
							list.add(pw);
							
							String msg = null;
							while((msg=br.readLine())!=null) {
								msg = "["+addr.getHostAddress()+ "]" +msg;
								for (int i = 0; i < list.size(); i++) {
									PrintWriter w = list.get(i);
									w.println(msg);
									w.flush();
								}
								System.out.println(msg);
							}
							
							
							
							if(pw!=null) pw.close();
							if(br!=null) br.close();
							if(osw!=null) osw.close();
							if(isr!=null) isr.close();
							if(is!=null) is.close();
							if(os!=null) os.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				});
				thr.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

네트워크 모델 (OSI 7계층 과 네트워크 4계층)


1-2 계층은 하드웨어 영역
3-4 계층은 운영체제 영역
5-7 계층은 프로그램 영역

TCP 방식 연결

연결지향방식으로 데이터 패킷을 보내는데 서로 응답을 주고 받음으로써 연결을 확인하는 방식
서버로 요청을 보내고 응답을 받고 다시 또 응답을 잘받았다는 요청을 보내면서 데이터패킷을 일부 보내는 과정이 반복된다.
서버에서도 응답을 잘 받았다는 요청을 받음으로써 요청을 받을 준비를 한다. 이후 패킷을 받을 때마다 받았다는 응답을 보낸다.
장점은 안전하다. loss가 없다. 서버로 부터 응답을 못받으면 정상적인 응답을 받을 때 까지는 패킷을 다시 보낸다.
단점은 느리다. 뭐하나 보낼 때마다 계속 응답을 확인하기 때문

UDP 방식 연결

패킷을 일방적으로 보내는 방식. 각 패킷마다 도착지점을 가지고 있다.
장점은 속도가 빠르다.
단점은 loss가 있을 수 있으며 데이터에 대한 무결성이 확보 되지 않는다. 신뢰도가 떨어진다.
브로드캐스트상황 - 인터넷 전화,온라인 게임,멀티미디어 스트리밍 등과 같은 실시간으로 데이터를 송/수신하는 서비스에 있어 많이 이용된다.

UDP 통신 구현

Sender

public class Sender {
	// UDP 통신
	public static void main(String[] args) {
		DatagramSocket sock = null;
		DatagramPacket packet = null;
		InetAddress addr = null;
		byte[] arr = {127,0,0,1};
		try {
			addr = InetAddress.getByAddress(arr);
			sock = new DatagramSocket();
			packet = new DatagramPacket("abcdefghqrs".getBytes(), 9, addr, 8080);
			sock.send(packet);
			
			packet = new DatagramPacket("1234".getBytes(), 4, addr, 8080);
			sock.send(packet);
			
			if(sock!=null)sock.close();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

Receiver

public class Receiver {

	public static void main(String[] args) {
		DatagramSocket sock = null;
		DatagramPacket packet = null;
		byte[] buf = new byte[16];
		try {
			sock = new DatagramSocket(8080);
			packet = new DatagramPacket(buf, 8);
			sock.receive(packet);
			buf = packet.getData();
//			byte[] buf2 = packet.getData();
//			System.out.println(buf == buf2); //true
			System.out.println(Arrays.toString(buf)); 
			
			packet = new DatagramPacket(buf, 4);
			sock.receive(packet);
			packet.getData();
			System.out.println(new String(buf));
			
			if(sock!=null)sock.close();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}