본문 바로가기
코딩도전기/JAVA

CODO Day30_JAVA(Network)

by 코도꼬마 2023. 3. 16.

JAVA Network

  • Network는 서로 다른 computer끼리 연결되어있는 망을 의미
  • Computer가 사물(Thing)로 변화하면서 IOT(Internet Of Things)가 됨 / ex) 인터넷 냉장고 등 
  • client는 server를 찾아가 특정한 목적을 이루기위해 request를 하고 response를 받음
  • 서로 다른 computer끼리 연결하기 위해서는 주소가 필요함
IP Port Domain
211.147.68.35 :8080 www.java.com
PC 주소 web에서 연결할 주소 찾아오기 쉽도록 지어준 이름

 

 

IP 주소 얻기

  • java로 IP 주소 가져오기
local IP 얻기 InetAddress ia = new InetAddress.getLocalhost( );
domain으로 IP 얻기 InetAddress ia = new InetAddress.getByName( String host);
domain에 연결된 전체 IP 얻기 InetAddress[ ] ipArr = new InetAddress.getAllByNames( String host);

 

  • GetIp
package chap02.ex01;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class GetIp {

	public static void main(String[] args) throws Exception {

		//내 PC의 IP 확인
		InetAddress addr = InetAddress.getLocalHost();
		System.out.println("내 PC 주소 확인 : "+addr.getHostAddress()); //192.168.12.33
		
		System.out.println();
		
		//특정 도메인에 연결된 주소
		String domain = "www.gdu.co.kr";
		addr = InetAddress.getByName(domain);
		System.out.println(domain+"에 연결된 IP : "+addr.getHostAddress());
		
		System.out.println();

		//대형사이트 하나에 여러 IP가 붙어있을 경우
		domain = "www.youtube.com";
		InetAddress[] addrs = InetAddress.getAllByName(domain);
		for (InetAddress inet : addrs) {
			System.out.println(inet.getHostAddress());
		}
		
		System.out.println();
		
		addrs = InetAddress.getAllByName("www.naver.com");
		for (InetAddress inet : addrs) {
			System.out.println(inet.getHostAddress());
		}
		
	}
	//공인IP(192.xxx) - 절대경로 : 다른 컴퓨터에서 접근할 수 있도록 상세주소
	//사설IP - 상대경로 : 다른 컴퓨터에서 접근할 수 없도록 
}

 

 

TCP(Transmission Control Protocol)

  • 연결지향 프로토콜로, 데이터를 안전하고 정확하게 전달
  • 단점은 데이터를 보내기 전에 반드시 연결을 형성해야 하고, UDP보다 속도가 느림
    • TCP : 해당 순서의 데이터가 들어오지 않을 경우 들어올 때 까지 기다림
      UDP : 해당 순서의 데이터가 들어오지 않으면 다음 데이터로 넘어감(데이터 유실 신경X)
  • client가 server에 접속하려면 Socket이 필요함  >>  소켓통신
    • Client(Socket)  :  자신의 정보를 보내 연결 요청  /  요청이 수락되면 서버 정보를 얻음
    • Server(Server Socket)  :  연결을 수락  /  연결이 수락되면 클라이언트 소켓의 정보를 얻음

 

  • TCP를 이용하여 Server 접속
Server Client
Server Socket 생성 Socket 생성
Client가 들어오고 싶어하는 IP 개방 socket을 통해 접속요청
Client 의 요청 대기 예외가 발생하지 않으면 접속 완료
요청이 있을 경우 특정 작업 처리 Socket 자원반납
Socket 자원 반납 및 종료(서버가 돌아가는 동안에는 생략) 종료

 

  • Server
package chap02.ex02;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

	public static void main(String[] args) {
		ServerSocket server = null; //내 소켓
		//1.서버 소켓 생성
		try {
			server = new ServerSocket(5001);			
			
			while(true) { //2.손님 대기 / 요청을 계속 받아주기 위해 반복문 사용
				System.out.println("손님 기다리는 중..");
				
				//3.접속 요청이 왔을 경우 수락(socket 안에는 손님의 모든 정보가 담김)
				Socket socket = server.accept(); //손님 소켓 / 소켓이 반환될 때 까지 blocking
				
				//4.해야할 일 실행(손님의 IP와 port번호를 알아냄)
				//getRemoteSocketAddress : 원격지의(client computer) 소켓주소
				InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
				System.out.println("접속완료 : " + addr.getAddress()+":"+addr.getPort());
			}
			
		} catch (IOException e) {
			e.printStackTrace();
			//5.소켓 반납(예외 발생 시 - 서버는 항상 켜져있기 때문)
			if(!server.isClosed()) { //서버가 닫혀있지 않으면
				try {
					server.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		
	}

}

 

  • Client
package chap02.ex02;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

	public static void main(String[] args) {
		Socket socket = null;
		//1.소켓생성 & 2.접속요청 / client도 요청이 계속 있을 경우 while문 사용
		try {
			socket = new Socket("localhost", 5001);
			System.out.println("접속 성공");
		} catch (Exception e) {			
			System.out.println("접속 실패"); //접속 실패 시 예외 발생
		}finally { //3.접속종료
			if(!socket.isClosed()) {
				try {
					socket.close();
				} catch (IOException e) {
				}
			}
		}

	}

}

 

 

Echo Server

  • Client와 Server가 접속하면 Stream을 통해 data를 전송 할 수 있음
  • Echo Server  :  Server or Client로 부터 받은 내용을 응답
  • Echo Server 진행순서
Server Client
Server Socket 생성 socket 생성
Client가 들어오고 싶어하는 IP 개방 socket을 통해 접속요청
Client의 요청 대기 예외가 발생하지 않으면 접속완료
Input Stream으로 데이터 수신 Output Stream으로 데이터 발신
Output Stream으로 데이터 발신 Input Stream으로 데이터 수신
Socket 자원 반납 및 종료(생략) Socket 자원 반납 및 종료

 

  • EehoServer
package chap02.ex04;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {

	public static void main(String[] args)  throws Exception{
		//1.서버소켓 준비
		ServerSocket server = new ServerSocket(7788);
		//2.요청대기&접속수락
		while(true) {
			System.out.println("요청대기중..");
			Socket socket = server.accept();
			System.out.println("접속수락");
			
			//3-1.요청확인 : Hello Server 문자열 출력
			InputStream is = socket.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(is);
			String msg = ois.readUTF();
			System.out.println("클라이언트에서 보낸값 : "+msg);
			
			//3-2.요청처리 : Hello Client라고 응답
			OutputStream os = socket.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(os);
			oos.writeUTF("Hello Client");
			oos.flush();
			oos.close();
			ois.close();
			//4.서버종료(생략)
			//server.close();
		}		
	}
}

 

  • EchoClient
package chap02.ex04;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class EchoClient {

	public static void main(String[] args)  throws Exception{
		//1.소켓생성&서버접속요청
		Socket socket = new Socket("192.168.12.59", 5555);
		System.out.println("접속성공");
		//2-1.요청	: sever에 Hello Server라고 보냄	
		OutputStream os = socket.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(os); //다른 언어는 Object로 보낼수없음
		oos.writeUTF("Hello Server");
		oos.flush();
		
		//2-2.요청에 대한 응답 확인 : Hello Client 출력
		InputStream is = socket.getInputStream();
		ObjectInputStream ois = new ObjectInputStream(is);
		String msg = ois.readUTF();
		System.out.println("서버에서 보내온 값 : "+msg);
		
		//3.소켓 종료
		ois.close();
		oos.close();
		socket.close();
	}
}

 

 

webserver 정보 받아오기 & 출력하기

  • WebServer
package chap02.ex05;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class WebServer {

	public static void main(String[] args) throws IOException {
		
		ServerSocket server = new ServerSocket(8080); //서버생성
        
		//pool 생성 - 여러 서버 받기 위해
		ExecutorService pool = Executors.newCachedThreadPool(); 
		
		while(true) { //요청대기
			System.out.println("요청대기중..");
			
			Socket socket = server.accept();
			System.out.println("접속수락");
			
			//해야할 일 지정(Runnable)
			Runnable run = new Runnable() {				
				@Override
				public void run() {
					try {
						//소켓에서 스트림 얻어오기
						InputStream is = socket.getInputStream(); 
						BufferedInputStream bis = new BufferedInputStream(is);
						//http protocol에서 지정한 최대 받을 수 있는 기본 크기
						byte[] arr = new byte[65536];
						bis.read(arr); //읽고 나서
						//출력
						String str = new String(arr);
						System.out.println(str);
						
						//응답하기(response)
						OutputStream out = socket.getOutputStream();
						PrintStream ps = new PrintStream(out);
                        
                        //web에 출력
						//헤더
						ps.print("HTTP/1.1 200 \r\n");
						ps.print("Content-type: text/html \r\n");
						ps.print("\r\n");
						
						//바디
						ps.print("<h3>Success Response</h3>");
						
						//자원반납
						ps.flush();
						bis.close();
						ps.close();
						socket.close();						
						
					} catch (IOException e) {
						e.printStackTrace();
					}					
				}
			};			
			//실행(execute)
			pool.execute(run);			
		}
		//서버소켓&스레드풀 종료(생략)
	}
}