[Java] 13_네트워크(Network)

2022. 8. 17. 12:20·📗 self-study/📗 KH정보교육원 당산지원

13_네트워크(Network)

 

 네트워크: Net(그물망) + work(일) == 여러 대의 컴퓨터들이 그물망처럼 얽히고 설켜 일을 할 수 있는 구조

여러 대의 컴퓨터를 통신 회선으로 연결한 것(홈 네트워크, 지역 네트워크, 인터넷 등이 해당)

 

서버 (== 가게주인) 클라이언트의 요청이 있기 전까지는 항상 대기 상태
                          클라이언트의 요청을 받고 해당 내용을 처리 후 응답을 보냄
클라이언트 (== 손님) 서버의 IP, port번호를 통해 필요로 하는 데이터를 요청함
IP주소 네트워크상에서 컴퓨터를 식별하는 번호(== 컴퓨터의 주소지)
=> 고유한 식별값이므로 같은 네트워크 안의 ip주소는 중복될 수 없음
포트(Port) 같은 컴퓨터 내에서 프로그램을 식별하는 번호(== 상세주소)
=> 고유의 식별값이므로 중복 불가
== 상대방의 IP주소와 포트 번호를 알고 있어야 데이터를 주고받을 수 있음

*네트워크(Network)
여러 대의 컴퓨터들이 연결되어 있는 통신망을 일컫는 용어
네트워크를 통해 서로간의 데이터들을 교환 가능함
 
*IP주소와 port번호
- IP주소: 네트워크상에 각 컴퓨터들을 식별할 수 있는 고유의 주소 번호
 (중복 불가, 컴퓨터의 주민번호)
- port번호: 컴퓨터 안에 작동하는 프로그램을 찾을 때
     각각의 프로그램을 식별해 주는 내부 주로
=> IP 주소와 port번호는 고정값이 아니라 변동이 가능한 유동적인 값임
     단, 값을 바꿀 때 IP주소 같은 경우 같은 네트워크 범위 안에서
    port번호 같은 경우 같은 컴퓨터 범위 안에서 중복이 일어나면 충돌 일어남
 
 *서버와 클라이언트
- 서버: 클라이언트(고객)에게 서비스를 제공하는 PC 또는 프로그램
 즉, 클라이언트의 요청을 처리해서 응답해 주는 역할 => 요청이 언제 들어올지 모르니 항상 켜져 있고 대기해야 하는 상태
- 클라이언트: 서버에 요청하는 PC 또는 프로그램을 일컫는 단어
 즉, 서비스를 제공받는 역할
=> 클라이언트 입장에서는 서버에 요청을 하기 위해서는 항상 그 요청하고자 하는 서버의 IP주소, port번호를 알고 있어야 함

 

<사용 메소드>

localHost: 지역 호스트 => 나의 PC를 지칭

.getlocalHost(): 나의 PC에 대한 정보를 반환

.getHostName(): pc명 반환

.getHostAddress(): IP주소 반환

 

InetRun 클래스

	public static void main(String[] args) {
		
		// InetAddress: 네트워크 정보(IP주소 관련)를 확인할 수 있는 클래스
		
		try {
			InetAddress localhost = InetAddress.getLocalHost();
			// localhost: 지역호스트 => 내 PC를 지칭
			// getLocaHost(): 내 PC에 대한 정보를 반환해 주는 메소드 (InetAddress 형태로 반환)
			
			System.out.println(localhost); // 내 PC명 + "/" + 내 IP주소
			
			System.out.println("내 PC명: " + localhost.getHostName());
			System.out.println("내 IP주소: " + localhost.getHostAddress());
			
			System.out.println("--------------------------------------");
			
			// 내가 알고 있는 "도메인 주소"를 제시해서 그 서버와 관련된 정보를 얻기
			// 도메인 주소: 사용자가 웹사이트에 접속할 때 매번 IP주소를 외우기 어렵기 때문에
			// 			  외우기 쉬운 구조로 사용자에게 제공해 주는 주소
			
			// 원래의 구조: IP주소 ----------------------------------------------> 바로 접속
			// 도메인 주소 적용: 도메인 주소 -----> DNS(Domain Name Server) -----> IP주소로 연결
			
			// 구글의 정보를 InetAddress 객체에 담기
			InetAddress googleHost = InetAddress.getByName("www.google.com");
			// getByName(): 도메인 주소라는 고유한 주소를 통해서 해당 서버 PC의 정보를 얻어내서 반환(InetAddress 형태로 반환)
			
			System.out.println(googleHost);
			System.out.println("구글 서버명: " + googleHost.getHostName());
			System.out.println("구글 IP주소: " + googleHost.getHostAddress());
			// 대형 사이트의 서버는 여러 개로 이루어져 있음!! (분산구조)
			// => 한 곳에만 요청이 몰빵될 경우 서버에 과부화 걸림
			
			System.out.println("--------------------------------------");
			
			// 도메인 주소를 통해서 그 서버 관련한 것들을 배열로도 받아 볼 수 있음
			InetAddress[] naverHost = InetAddress.getAllByName("www.naver.com");
			
			System.out.println("네이버 서버 개수: " + naverHost.length);
			
			// 반복문 돌려가며 모든 서버의 정보 출력
			/*
			for(int i = 0; i < naverHost.length; i++) {
				System.out.println(i + "번째 서버: " + naverHost[i]);
			}
			*/
		
			// 향상된 for문
			// for(변수선언문 : 반복돌배열명)
			for(InetAddress n : naverHost) {
				System.out.println(n);
			}
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
     }

 

 * 현재 구동 중인 서버가 있으면 클라이언트는 그 서버로 요청을 보낼 수 있음
=> 응답 결과가 항상 돌아옴!
 
요청과 응답에 의해서 프로그램은 돌아감("통신"한다라고 표현)
=> 웹에서의 통신 방식: HTTP 프로토콜 통신(HTTPS: HTTP에 보안 절차가 추가된 버전)
 
*자바만을 가지고 서버와 클라이언트 간의 간단한 통신 해 보기
=> 이때 데이터를 입출력하고자 한다면 서버와 클라이언트 간에 스트림 (연결 통로)가 있어야 함!



바로 이렇게...!

*소켓: 프로세스간에 통신을 담당하는 것
   즉, 스트림을 연결하기 위한 문
 


*소켓 프로그래밍(TCP 방식 / UDP 방식)
- TCP방식: 데이터 전송 속도가 느리나 데이터를 정확하고 안정적으로 전달 가능함
  주로 신뢰성이 요구되는 프로그램에서 많이 사용(웹, 이메일, 파일전송, ...)
- UDP방식: 데이터 전송 속도는 빠르나 신뢰성이 없는 데이터가 전송될 수 있음(중간에 데이터 손실될 가능성 있음)
   주로 데이터를 빠른 속도로 전송하고자 하는 프로그램에서 사용(실시간 스트리밍)

 

*TCP(Transmission Control Protocol)
- 서버, 클라이언트간의 1:1 소켓 통신 방식
- 데이터를 교환하기에 앞서서 서버, 클라이언트에 연결되어 있어야 함
  (항상 서버가 먼저 실행되어 클라이언트의 요청을 기다릴 것)
- 신뢰성 있는 데이터 전달 가능
 
*Socket
- 프로세스 간의 통신을 담당
- Socket 프로그래밍을 위한 기반스트림인 Input / OutputStream을 가지고 있음
- 기반스트림만으로는 제한이 있으니 보조스트림을 추가시켜 성능을 향상시킬 것
 
*ServerSocket
- 포트번호와 연결(Bind: 엮다)되어 외부의 연결 요청을 기다리다 연결 요청이 들어오면 수락해 줄 용도
   수락하는 순간 Socket 객체가 생성됨!

 

<진행 순서>
 0. 소켓 만들기
1. 스트림 열기
2. 볼 일 보기
3. 스트림 끊기

 

ServerProgram 클래스

package com.kh.chap02.tcp.run;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

// 서버용 프로그램
public class ServerProgram {

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);

		// 1) 이 프로그램에서 사용할 port번호 지정
		// => 서버측에서 몇 번 포트로 통로를 열겠냐는 의미
		int port = 3000;

		ServerSocket server = null;
		BufferedReader br = null;
		PrintWriter pw = null;
		
		// 2) ServerSocket 객체 생성 및 포트 결합(Bind)
		// => 앞으로 클라이언트의 연결 요청을 받아 줄 용도로 사용됨
		try {
			server = new ServerSocket(port);

		// 3) 클라이언트로부터 접속 요청이 들어올 때까지 대기 상태
			System.out.println("클라이언트의 요청을 기다리고 있습니다..");
			
		// 4) 연결 요청이 오면 요청을 수락 후 해당 클라이언트와 통신할 수 있는 Socket 객체가 생성됨
			Socket socket = server.accept(); // socket == 클라이언트와  통신하기 위한 소켓 객체
			
			// 상대방의 정보 얻기: getInetAddress() 메소드 사용
			System.out.println(socket.getInetAddress().getHostAddress() + " 가 연결을 요청함..");
			
		// ----- 이 시점까지 연결하겠다고 약속은 된 상태, 아직 스트림은 열리지 않음 -----
			
		// 5) 클라이언트와 통신할 수 있는 입력용, 출력용 스트림을 생성 => socket 객체에서 제공해 줌
		// 6) 보조스트림을 추가하여 성능 개선
			
		// 입력용 스트림(클라이언트로부터 전달된 값을 한 줄 단위로 읽어들일 수 있게끔)
		// socket.getInputStream()
		// + 1byte 와 2byte 사이의 호환이 가능한 보조 스트림(InputStreamReader)
		// BufferedReader
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		
		// 출력용 스트림 (클라이언트에게 값을 전달할 용도)
		// socket.getOutputStream()
		// + 1byte 와 2byte 사이의 호환이 가능한 보조 스트림(OutputStreamWriter)
		// PrintWriter
			pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			
			// => 기반스트림에 성능 향상을 위해 보조스트림을 각각 2개씩 붙여 줌
			
		// 7) 클라이언트와 스트림을 통해 읽고 쓰기
		// => 통신을 주거니 받거니 반복을 위한 반복문
			while(true) {
				
				// 클라이언트로부터 전달된 메시지가 있을 경우 서버측에서 읽어들이기(input)
				String message = br.readLine();
				System.out.println("클라이언트로부터 전달받은 메시지: " + message);
				
				// 반대로 클라이언트에게 데이터를 전달하기(output)
				System.out.println("클라이언트에게 보낼 내용: ");
				String sendMessage = sc.nextLine();
				
				pw.println(sendMessage); // 클라이언트에게 1줄 단위로 출력
				
				pw.flush(); // 현재 스트림에 남아 있는 잔여 데이터를 강제로 내보내는 역할을 해 주는 메소드
							// 여태까지는 입출력 후 자원 반납 해 주었기 때문에 flush 메소드를 쓰지 않았음
							// 자원 반납 시 자동으로 flush()가 진행되기 때문!
							// 지금은 주고받고 해야 하니까 스트림 막힐까 봐 flush() 메소드를 사용함
			}
			
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			
			// 8) 통신 종료를 위한 자원 반납(생성된 순서의 역순으로)
			
			try {
				pw.close();
				br.close();
				server.close();
			} catch (IOException e) {
				e.printStackTrace();
		
			}
			
		}
		
	}

}

 

ClientProgram 클래스

package com.kh.chap02.tcp.run;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientProgram {

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		Socket socket = null;
		BufferedReader br = null;
		PrintWriter pw = null;
		
		// 1) 접속하고자 하는 서버의 IP주소, port번호 지정
		// 요청하고자 하는 서버의 IP주소: 192.168.40.30 또는 127.0.0.1 (루프백 IP) 또는 localhost
		String serverIP = "127.0.0.1";
		int port = 3000;
		
		// 2) 서버에 연결 요청을 보내는 구문
		// => 요청하고자 하는 서버의 IP주소와 port번호를 제시하면서 Socket 객체 생성
		try {
			socket = new Socket(serverIP, port);
			// => Socket 객체 생성 시 연결이 제대로 되었다면 객체가 잘 생성될 것
			//					    연결이 실패할 경우에는 null 값이 Socket 객체에 담김
			
			// NullPointerException은 충분히 예상 가능한 오류이기 때문에 조건문으로 선처리
			if(socket != null) { // 연결이 잘되었을 경우 => 통신 진행
				System.out.println("서버와 연결 성공!");
				
			// 3) 서버와 통신할 수 있는 입력용 스트림, 출력용 스트림 열기
			// 4) 보조 스트림을 추가하여 성능 개선
				
				// 입력용 스트림
				// socket.getInputStream() + InputStreamReader + BufferedReader
				br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				
				// 출력용 스트림
				// socket.getOutputStream() + OutputStreamWriter + PrintWriter
				pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
				
				// 반복문
				while(true) {
					
			// 5) 스트림을 통해 읽고 쓰기
			// 서버에게 데이터를 전달 (output)
					
					System.out.print("서버에게 보낼 내용: ");
					String sendMessage = sc.nextLine();
					pw.println(sendMessage);
					pw.flush();
					
			// 서버로부터 전달된 메시지를 읽어들이기 (input)
					
					String message = br.readLine();
					System.out.println("서버로부터 전달받은 메시지: " + message);
					
				}
				
			}
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			
			try {
				pw.close();
				br.close();
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

헐

개쩐다

저작자표시 (새창열림)
'📗 self-study/📗 KH정보교육원 당산지원' 카테고리의 다른 글
  • [Java] 14_컬렉션(Collection)의 개요
  • [8/18 시험 대비]
  • [Java] 12_IO(보조 스트림을 이용한 객체, 객체배열 단위 입출력)
  • [Java] 12_입출력[바이트 기반 스트림(== 좁은 통로)과 문자 기반 스트림(== 넓은 통로)의 입출력, 보조 스트림의 개요 및 입출력]
천재강쥐
천재강쥐
  • 천재강쥐
    디버거도 버거다
    천재강쥐
  • 전체
    오늘
    어제
    • Category (467)
      • 진짜 너무 궁금한데 이걸 나만 몰라...? (0)
      • 💾 Portfolio (2)
      • 🐤 CodingTest (28)
        • Java (20)
        • ᕕ(ꐦ°᷄д°᷅)ᕗ❌ (5)
      • 🚀 from error to study (142)
        • AI (1)
        • Cloud (2)
        • DB (12)
        • Front-End (16)
        • Github (14)
        • Java (39)
        • Mac (7)
        • Normal (29)
        • Server (22)
      • 📘 certificate (44)
        • 📘 리눅스마스터1급 (1)
        • 📘⭕️ 정보처리기사 (40)
        • 📘⭕️ SQLD (3)
      • 📗 self-study (234)
        • 📗 inflearn (35)
        • 📗 생활코딩 (8)
        • 📗 KH정보교육원 당산지원 (190)
      • 🎨 Scoop the others (0)
        • 📖 Peeking into other people.. (0)
        • 🇫🇷 (0)
        • 📘⭕️ 한국사능력검정시험 심화 (11)
        • 오블완 (4)
  • 인기 글

  • hELLO· Designed By정상우.v4.10.1
천재강쥐
[Java] 13_네트워크(Network)
상단으로

티스토리툴바