클라이언트와 서버 간의 데이터 이동 처리
네트워크 통신 네트워크 작업은 늘 try-catch문 필요
통신규약 [Protocol]
서버와 통신하기 위한 규약
1. IP (Internet Protocol)
아이피 주소 중 특별하게 쓰는 번호가 있음
127.0.0.1 : 특정한 컴퓨터 번호 말하는 것이 아니고 내가 내 주소를 부르는 것 (루프 백 주소)
🧨 용어 정리
컴퓨터 안에는 프로그램이 여러개 이고 인터넷을 통신하는것도 한개 이상임 랜선 하나로 프로그램들을 구분해야함 컴퓨터 까지 오는것이 아이피 어느 프로그램으로 줄것인가가 포드번호
ex) 부산항(IP번호) 3번 항구(port 번호)
1) IP 주소 / 도메인 : 컴퓨터의 고유한 주소(숫자) : 42억개..
2) 포트번호 : 그 컴퓨터 안에서의 동작하는 프로그램
고유번호(65천개) : 0~1024번(well-known port)까지는 사용하지 않는 것을 권장
통신을 하려면 일단 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
서버에서는 데이터를 받고 클라이언트에서는 데이터를 보내는 형식의 예제
1) 서버소켓을 만들어 내는 작업
2) 클라이언트 접속 기다리기
3) 클라이언트로부터 데이터 읽어오는 인풋 스트림
4) 클라이언트가 outputStream을 통해 보내온 데이터를 input으로 읽기
5) 스트림 닫기
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();
}
}
}
1) 서버와 연결하는 Socket생성(IP주소 , port번호)
2) 데이터를 전달하기 위한 무지개로드(Stream) 만들기
3) 스트림을 통해 데이터 전송
4) 스트림 찌꺼기 내리기
5) 스트림 닫기
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();
}
}
}
Sender 에서 Receiver로 데이터 보내는 실습
1) 우편을 보낼 우체통인 DatagramSocket 만들기
2) 보낼데이터 준비
3) 보낼 데이터를 우편으로 보내기 위해 택배상자(DatagramPacket)준비
(Packet : 데이터를 분할하는 단위)
4) 우체통에 택배박스를 보내기
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();
}
}
}
1) DatagramPacket을 받을 우체통 준비(DatagramSocket)
2) 받은 우편물의 내용(데이터)을 담을 수 있는 빈 박스(DatagramPacket) 준비하기
3) 우체통에 택배가 오길 기다린다
4) byte[] 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가 이뤄지는 것과 달리 실시간으로 전송되고 처리되는 모습이 흥미로웠다