네트워크(Network)

소정·2023년 2월 6일
0

Java

목록 보기
23/23
post-custom-banner

네트워크

클라이언트와 서버 간의 데이터 이동 처리
네트워크 통신 네트워크 작업은 늘 try-catch문 필요

통신규약 [Protocol]
서버와 통신하기 위한 규약
1. IP (Internet Protocol)

  • 특정한 개인과 통신하기위한 식별자
  • 정수형 숫자를 바이트(~255) 단위로 자르고 사이사이에 점을 찍어 구분하기로 약속
  • 아이피 주소는 문자열임
    도메인 - 외우기어려운 숫자대신 문자로 변형한 주소값, DNS가 도메인을 IP로 바꿔 전달해줌

아이피 주소 중 특별하게 쓰는 번호가 있음
127.0.0.1 : 특정한 컴퓨터 번호 말하는 것이 아니고 내가 내 주소를 부르는 것 (루프 백 주소)

  1. TCP (Transmission Control Protocol)
  • 신뢰성이 있는 통신, 전화 방식과 비슷함 상대가 꼭 있다는 전제 하에 통신 블루투스가 이 방식을 사용함
  1. UDP (User Datagram Protocol)
  • 신뢰성 없는 통신, 편지 보내는 방식과 비슷함, 상대방이 있는지 없는지 상관없음 신뢰성이 없지만 속도가 빠름
    사용 예) 게임 좌표 보낼 때 사용
  1. SMTP (Simple Mail Transfer Protocol)
  • 이메일 전송 시스템
  1. FTP (File Transfer Protocol)
  • file 데이터 전송 할 때 쓰는 것 메타데이타 전송
  1. HTTP (Hyper Text Transfer Protocol)
  • 웹서비스 html 언어를 보여주기 위한 것
    respose/request규약

🧨 용어 정리
컴퓨터 안에는 프로그램이 여러개 이고 인터넷을 통신하는것도 한개 이상임 랜선 하나로 프로그램들을 구분해야함 컴퓨터 까지 오는것이 아이피 어느 프로그램으로 줄것인가가 포드번호
ex) 부산항(IP번호) 3번 항구(port 번호)
1) IP 주소 / 도메인 : 컴퓨터의 고유한 주소(숫자) : 42억개..
2) 포트번호 : 그 컴퓨터 안에서의 동작하는 프로그램
고유번호(65천개) : 0~1024번(well-known port)까지는 사용하지 않는 것을 권장


자바에서 IP 주소 확인 방법

통신을 하려면 일단 IP주소는 알아야함
InetAddress : 자바에 IP주소에 관련된 정보를 가지고 있는 클래스

//본인의 아이피주소를 확인하는 방법	
try {
	System.out.println(InetAddress.getLocalHost().getHostAddress()); //172.00.0.00
	System.out.println(InetAddress.getLocalHost().getHostName()); // DESKTOP-9UDT4MQ : 컴터 이름
	System.out.println(InetAddress.getLocalHost().toString());  //DESKTOP-9UDT4MQ/172.00.0.00
	System.out.println(InetAddress.getLoopbackAddress().getHostAddress()); //내 컴터에서 내 컴터 부를 때:127.0.0.1
	System.out.println(InetAddress.getLoopbackAddress().getHostName()); //내 컴퓨터에서 내 컴터 부르는 도메인 : localhost
	
} catch (UnknownHostException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

LoopbackAddress : 내 컴퓨터 부르는 방법\
컴퓨터 고유 아이피를 사용하지 않고 약속된 아이피/ 도메인으로 내 아이피 주소 얻어오기
1) 아이피 : 127.0.0.1
2) 도메인 : localhost

소켓통신 2종류

[1] TCP (Transmission Control Protocol)

  • 교환기 같은 녀석을 두고 그 놈을 통해 통신을 주고 받음 클라이언트끼리 연결해 두지말고 중간매체인 서버를 통해 통신함
  • 데이터 손실이 없도록 안정성 보장
  • TCP통신은 서버용 프로그램과 Client역할을 할 프로그램 두개가 있어야 동작함

  • 서버 소켓에 소켓은 Client가 접속해야 만들어짐
  • Client에서 소켓을 생성 할 때 서버의 아이피 주소와 포트 번호가 필요하다
  • 서버소켓과 클라이언트의 소켓이 연결되고 데이터를 보낼땐 스트림이 필요한데 받는 쪽에선 input 보내는 쪽에선 output 스트림 두개가 붙어 있는 듯한 모양으로 있다

TCP통신 예제

서버에서는 데이터를 받고 클라이언트에서는 데이터를 보내는 형식의 예제

server용 프로그램 작성

1) 서버소켓을 만들어 내는 작업

  • ServerSocket 키워드로 객체 생성

2) 클라이언트 접속 기다리기

  • serverSocket.accept()으로 클라이언트 접속 길 열어두고 리턴값이 Socket으로 받는다
  • .accept() : 클라이언트 요청을 받는 메소드

3) 클라이언트로부터 데이터 읽어오는 인풋 스트림

  • 소켓으로 통신했으니 소켓으로 접근함, 바이트로 오기때문에 한번에 받기 편하게 보조 문자 스트림으로 변환하여 받음
    InputStream inst = socket.getInputStream() //바이트 스트림
    InputStreamReader isr = new InputStreamReader(inst); //문자 스트림
    BufferedReader reader = new BufferedReader(isr); //보조 문자 스트림

4) 클라이언트가 outputStream을 통해 보내온 데이터를 input으로 읽기

  • 받아온 데이터를 inputStream을 통해 읽는다
  • 이때 스트림은 일회용이기 때문에 문자를 여러번 받고싶으면 반복문을 돌린다
    String msg = reader.readLine();

5) 스트림 닫기

  • 스트림은 꼭 닫아줘야 데이터 누수가 없다
    reader.close();
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class ServerTest {

	public static void main(String[] args) {

		//server용 프로그램 작성
		try {
			//1. 서버소켓을 만들어 내는 작업
			ServerSocket serverSocket = new ServerSocket(10006);//서버소켓은고유 번호 필요 - 포트번호
			
			System.out.println("서버소켓 생성");
			
			//2. 클라이언트 접속 기다리기
			System.out.println("클라이언트의 접속을 기다립니다...");
			Socket socket =serverSocket.accept(); //리턴값이 Socket - 클라이언트가 생성함
			//여기서 커서(스레드)가 대기함
			
			System.out.println("Client가 접속함");
			
			//3. 클라리 언트로부터 데이터 읽어오는 인풋 스트림
			InputStream inst  = socket.getInputStream(); //바이트 스트림
			InputStreamReader isr = new InputStreamReader(inst); //문자 스트림
			BufferedReader reader = new BufferedReader(isr); //보조 문자 스트림
			
			//4. 클라이언트 outputStream을 통해 보내온 데이터 읽기
			//4-1) 한번만 읽음
			//String msg = reader.readLine();
			//System.out.println("받은 메세지 : " + msg);
			
			//4-1) 여러번 읽음 
			while(true) {
				String msg = reader.readLine();
				if(msg==null) break; //null은 client와 통신이 끊어 졌을 때(close) 
				System.out.println("받은 메세지 : " + msg);
			}
			
			
			//스트림 닫기
			reader.close(); //하위만 닫아도 알아서 닫힘
			
			System.out.println("서버통신 종료");
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		
		
	}

}

client용 작업 프로그램 작성

1) 서버와 연결하는 Socket생성(IP주소 , port번호)

  • 어느 서버에접근할 것인지에 대한 IP주소 , port번호 필요
    client 소켓은 Socket 키워드로 생성
    Socket socket = new Socket(serverIP, 10006);

2) 데이터를 전달하기 위한 무지개로드(Stream) 만들기

  • 데이터를 내보내는 스트림 : OutputStream
  • 소켓을 통해 스트림 생성해야함(바이트 단위)
  • 이때 보조 스트림을 사용하면 더 쉽게 데이터 보냄
    OutputStream os = socket.getOutputStream()
    PrintWriter pw = new PrintWriter(os);

3) 스트림을 통해 데이터 전송

  • 만든 스트림을 통해 데이터 보낸다
    pw.println(msg); //스트림 통해 보내기

4) 스트림 찌꺼기 내리기

  • pw.flush();

5) 스트림 닫기

  • 데이터 누수가 나지 않도록 스트림 닫기
    pw.close();
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientTest {

	public static void main(String[] args) {

		
		//클라이언트는 서버의 아이피주소와 포트번호를 알고 있어함
		
		//서버의 아이피 주소
		String serverIP = "172.30.1.89";
		serverIP = "127.0.0.1"; //루프백 아이피 - 내거
		serverIP = "localhost"; //내 컴퓨터 도메인(식별자)
		
		
		//클라이언트용 작업
		try {
			//1. 서버와 연결하는 Socket생성(ip주소 , port번호)
			Socket socket = new Socket(serverIP, 10006);
			System.out.println("서버와 연결됐습니다");
			
			//2. 데이터를 전달하기 위한 무지개로드(Stream) 만들기
			//데이터를 내보내는 스트림 : OutputStream
			
			OutputStream os = socket.getOutputStream(); //소켓을 통해 스트림 생성해야함
			//보조문자 스트림을 쓰면 write작업을 보다 수월하게 할수 있음
			PrintWriter pw = new PrintWriter(os);
			
			System.out.println("스트림 연결 작업 성공..데이터 전송 가능 상태");
			
			//보낼 데이터 키보드 입력
			Scanner sc = new Scanner(System.in);
			
			// 3. 스트림을 통해 데이터 전송
			//3-1) 메세지 한번만 보내짐 
//			System.out.print("보낼 메세지 입력 : ");
//			String msg= sc.nextLine();
//
//			pw.println(msg); //스트림 통해 보내기
//			pw.flush(); //스트림 찌꺼기 내리기
			
			//3-2) 메세지 여러번
			while(true) {
				System.out.print("보낼 메세지 입력 : ");
				String msg= sc.nextLine();
				
				if(msg.equalsIgnoreCase("quit")) break;

				pw.println(msg); //스트림 통해 보내기
				pw.flush(); //스트림 찌꺼기 내리기
			}
			
			pw.close(); // 스트림 닫기
			
			System.out.println("서버와 통신 종료");
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}

}

cmd 창으로 확인


[2] UDP(UserDatagram Protocol)

  • Receiver의 아이피 주소와 포트 번호는 알아야함
  • 받는 방식이 특이함 보낸 Data의 값만 툭 놓고 감 그래서 받는 쪽에서 미리 빈 Datagram을 준비해 둬야함
  • 보내는 쪽에선 받는 말든 그냥 보내버림 받든 말든 상관없음 -> 데이터 안정성 보장하지 않음 속도가 빠르다

UDP통신 예제

Sender 에서 Receiver로 데이터 보내는 실습

Sender

1) 우편을 보낼 우체통인 DatagramSocket 만들기

  • DatagramSocket socket = new DatagramSocket();

2) 보낼데이터 준비

3) 보낼 데이터를 우편으로 보내기 위해 택배상자(DatagramPacket)준비
(Packet : 데이터를 분할하는 단위)

  • 받는 사람 주소로 InetAddress객체 생성 (자바에서 IP 주소를 표현할때 사용하는 클래스)
    InetAddress addr = InetAddress.getByName("ReceiverIP");
  • 택배상자에 담기
    DatagramPacket drp = new DatagramPacket(msg.getBytes(),msg.getBytes().length, addr, 10001);
-> DatagramPacket의 매개 변수로 (바이트 배열형 데이터, 보낼 데이터의 사이즈, ReceiverIP, ReceiverPort )

4) 우체통에 택배박스를 보내기

  • 소켓을 이용하여 send()
    socket.send(drp);
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;

public class SenderTest {

	public static void main(String[] args) {

		// UDP : Usser Datagram Protocol 
		// 마치 택배보내기와 비슷, 속도가 빠른 방식
		
		try {
			//1. 우편을 보낼 우체통인 DatagramSocket 만들기
			DatagramSocket socket = new DatagramSocket();
			
			//2. 보낼데이터 준비
			Scanner sc =new Scanner(System.in);
			
			System.out.print("보낼 데이터 : ");
			String msg = sc.nextLine();
			
			//3. 보낼 데이터(msg)를 우편으로 보내기 위해 택배상자(DatagramPacket)준비
			// Packet : 데이터를 분할하는 단위
			InetAddress addr = InetAddress.getByName("172.30.1.89"); //받는 사람 주소로 InetAddress객체 생성
			DatagramPacket drp = new DatagramPacket(msg.getBytes(),msg.getBytes().length, addr, 10001); // 10001 : port번호
			
			//4. 우체통에 택배박스를 보내기
			socket.send(drp);
			
			System.out.println("전송 완료");
			
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

	}

}

Receiver

1) DatagramPacket을 받을 우체통 준비(DatagramSocket)

  • port번호를 써서 구분지어준다
    DatagramSocket sockat = new DatagramSocket(10001);

2) 받은 우편물의 내용(데이터)을 담을 수 있는 빈 박스(DatagramPacket) 준비하기

  • 빈 박스 만들기 준비
  • 데이터를 받을 바이트 배열과 박스를 준비
    byte[] buf = new byte[1024];
    DatagramPacket packet = new DatagramPacket(buf, buf.length);

3) 우체통에 택배가 오길 기다린다

  • 소켓으로 온 메세지를 받아서 packet안에 buf라는 배열안에 넣어줌
    sockat.receive(packet);

4) byte[] buf에 담긴 데이터를 문자열로 변환하여 화면에 출력

  • String msg = new String(buf);
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ReceiverTest {

	public static void main(String[] args) {

		try {
			//1. DatagramPacket을 받을 우체통 준비(DatagramSocket)
			DatagramSocket sockat = new DatagramSocket(10001);
			
			//2. 받은 우편물의 내용(데이터)을 담을 수 있는 빈 박스(DatagramPacket) 준비하기
			//빈 박스 만들기 준비
			byte[] buf = new byte[1024];
			DatagramPacket packet  = new DatagramPacket(buf, buf.length);
			
			//3. 우체통에 택배가 오길 기다린다 
			System.out.println("메세지를 기다립이다");
			
			sockat.receive(packet); //메세지를 받아서 packet안에 buf라는 배열안에 넣어줌. 메세지로 받을때까지 커서가 대기중
			
			//4. byte[] buf에 담긴 데이터를 문자열로 변환하여 화면에 출력
			String msg = new String(buf);
			
			System.out.println("반은 메세지 : "+ msg);
			
			
			
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}

}

결과 화면



소켓 통신은 처음 써봤는데 http는 사용자가 request를 보내야 respose가 이뤄지는 것과 달리 실시간으로 전송되고 처리되는 모습이 흥미로웠다

profile
보조기억장치
post-custom-banner

0개의 댓글