Java 정리 30
24 Dec 2018
Reading time ~4 minutes
Java 정리 30 - Network
네트워크
- 컴퓨터끼리 정보를 주고 받기 위한 통신망
- 협의적 의미
- 크기에 따라 LAN, MAN, WAN
- java.net 패키지에서 관련 클래스를 제공
- 다른 컴퓨터와 정보를 주고 받기위해 생성하고 연결에 사용하는 객체들
- Socket, ServerSocket
- TCP 방식 구현할 때
- DatagramPacket, DatagramSocket
- UDP 방식 구현할 때
- InetAddress
- 접속자의 정보를 얻을 때
- URLEncoder, URLDecoder
- 문자열을 변환할 때
- Socket, ServerSocket
- 위 클래스들은 연결만 수행, 데이터를 주고 받는 건 Stream
- 허브
- 네트워크에 존재하는 여러가지 컴퓨터를 모으는 일을 함.
- 라우터
- 목적지 컴퓨터의 최단거리를 산출, 관리
OSI 7 Layer Model (Reference Model)
- 실제로는 TCP/IP Model을 사용
- PD가 NT갔다가 SPA를 갔다(암기용)
- Application(응용) 계층
- 사용자 Application
- Presentation(표현) 계층
- 컴퓨터가 알아볼 수 있도록 반환
- 암호화
- Session(세션) 계층
- 가상 연결(호 단위 연결)
- Transport(전송) 계층
- 실제 연결
- TCP (Transmission Control Protocol)
- UDP (User Datagram Protocol)
- Network (네트워크) 계층
- 길찾기
- Data Link (데이터링크) 계층
- MAC 물리계층으로 데이터 연결
- Pysical (물리) 계층
- LAN선 사용 연결
- RJ45 이용
- LAN선 사용 연결
PDU (Protocol Data Unit)
- 데이터 통신에서 상위 계층이 전달한 데이터에 붙이는 제어정보
- header - 계층을 식별하기 위한 이름이 붙는다.
- body - payload data를 가짐
- 데이터 계층이 내려갈때마다 pdu들이 다른 계층의 payload로 들어가면서 길어진다.(캡슐화)
- 다른 클라이언트가 받은 패킷은 header를 읽고 payload를 역순으로 데이터를 올려보냄
TCP, UDP
- TCP (Transmission Control Protocol)
- 전화에 비유
- 패킷의 크기가 고정되어 있다.
- 1packet = 8bit(1byte)
- 신뢰성 통신 (오류 검출)
- 속도가 느리다.
- 오류검출하는 패킷이 존재
- 미전송 패킷을 다시 보낸다.
- 중요한 데이터를 보낼 때 사용(결제, 은행거래,..)
-
Socket, ServerSocket
- UDP(User Datagram Protocol)
- 우편에 비유
- 패킷의 크기를 변경할 수 있다.(최대 512byte)
- 비신뢰성 통신 (오류 검출 안함)
- 속도가 빠르다.
- 오류검출하는 패킷이 없음
- 반드시 데이터 전송되리란 보장이 없음
- 중요하지 않은 데이터를 전달할 때 사용(스트리밍, 화상전화, M2M(machine to machine)
- DatagramSocket, DatagramPacket
컴퓨터 환경의 변천사
- 중앙 집중식
- 한개의 서버가 존재, 여러 단말기가 붙은 형태
- 예) 하이텔 단말기
- 서버가 제공하는 데이터를 접목하여 사용
- RAIDUS 과금형태
- 한개의 서버가 존재, 여러 단말기가 붙은 형태
- Client - Server
- 서버가 존재하고 여러 클라이언트가 서버에 데이터를 요청하는 형태
- 프로그램 배포에 문제
- 문제 생기면 출장..
- Web 환경
- 웹서버가 존재, 웹 클라이언트(웹브라우저)들이 데이터를 요청하는 형태
- 웹서버로부터 화면을 받아 브라우저에서 그린다.
- 브라우저마다 다르게 그려짐 -> 웹표준 탄생의 계기
- 어디서나 접근가능(접근성)
- RIA 환경
- RIA(Rich Internet Application)
- 접속자의 자원을 더 많이 사용
- AJAX(Asynchronous JavaScript and XML)
- 요즘 게임환경은 C/S환경과 Web환경이 합쳐진 형태
- Web환경으로 프로그램 배포한 후 웹 브라우저가 감당하기 힘들기 때문에 배포된 프로그램으로 C/S환경으로 게임서버와 게임 클라이언트간 통신
- CS와 형태는 같음
- RIA(Rich Internet Application)
Network S/C 프로그래밍
Server
- 정보제공
- ServerSocket 생성
- 통신 port 열림 : port 선점
- 1024번 이하의 port는 이미 열려있는 port가 많다.
// 주어진 포트번호로 서버소켓 생성, 접속자가 들어오길 기다림
ServerSocket ss = new ServerSocket(포트번호);
- 접속자 소켓을 받는다.
Socket client = ss.accept(); // blocking
Client
- 정보를 요청
- 서버로부터 정보를 제공받는 애
- Socket 생성
- 입력된 ip address와 port를 가지고 서버연결 시도
Socket socket = new Socket(아이피주소,포트번호);
// SimpleServer
public class SimpleServer {
public SimpleServer() throws IOException {
// 1. PORT를 열고 접속자가 들어오기를 기다린다.
ServerSocket server = null;
try {
server = new ServerSocket(3000);
System.out.println("서버 가동중 "+server);
// 3. 접속자가 들어오면 접속자 소켓을 받는다.
Socket client = server.accept();
System.out.println("접속자 있음 "+client);
} finally {
if (server!=null) server.close();
}
}
public static void main(String[] args) {
try {
new SimpleServer();
} catch (IOException e) {
System.out.println("포트가 이미 사용중입니다.");
e.printStackTrace();
}
}
}
// SimpleClient
public class SimpleClient {
public SimpleClient() throws UnknownHostException, IOException {
// 2. 소켓을 생성 : 내 컴퓨터에 들어갈 때는 localhost 또는 127.0.0.1(루프백)
// 다른 컴퓨터에 들어갈 때에는 ip address
Socket client = new Socket("localhost",3000);
System.out.println("서버에 접속 하였습니다. "+client);
}
public static void main(String[] args) {
try {
new SimpleClient();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 방화벽 설정이 안돼 있으면 외부와 통신이 안될 수 있음
- 제어판에서 인바운드, 아웃바운드 규칙을 추가해 주어 해결
데이터 전송하기
- TCP는 패킷이 고정길이 1packet = 8bit(1byte)
Server
- 접속자 소켓을 받은 후 문자열 쓰기
- DataOutputStream 사용
- Java의 데이터형을 스트림으로 내보낼 때 사용하는 Stream
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
- 쓰기
- 입력된 문자열이 %로 분할(인코딩)되어 스트림에 기록
- flush로 스트림에서 분출
dos.writeUTF("문자열");
dos.flush();
Client
- 보내온 문자열을 읽기 위한 스트림을 사용
DataInputStream dis = new DataInputStream(socket.getInputStream())
- 읽기
- 인코딩된 한글을 원래대로 조립하여 보여준다.
dis.readUTF();
// 위와 동일한 SimpleServer 예제
public SimpleServer() throws IOException {
// 1. PORT를 열고 접속자가 들어오기를 기다린다.
ServerSocket server = null;
// 접속자에게 보내줄 메시지
String msg = "☆ ˚ * ˚★\n" +
" ▲ △ ▲ \n" +
"(^^)('')('')\n" +
"▶◀▶◀▶◀\n" +
"메리크리스마스\n" +
"해피뉴이어~ -오영근-";
// 접속자에게 메시지를 보내기 위한 스트림을 선언
DataOutputStream dos = null;
try {
server = new ServerSocket(3000);
System.out.println("서버 가동중 "+server);
while(true) { // 계속 실행
// 3. 접속자가 들어오면 접속자 소켓을 받는다.
Socket client = server.accept();
System.out.println("접속자 있음 "+client);
// 접속자에게 메시지를 보내기 위한 연결
dos = new DataOutputStream(client.getOutputStream());
// 얻어낸 스트림에 데이터 쓰기
dos.writeUTF(msg);
// 스트림의 데이터를 목적지(소켓)로 분출
dos.flush();
}
} finally {
if (server != null) server.close();
if (dos != null) dos.close();
}
}
public SimpleClient() throws UnknownHostException, IOException {
// 2. 소켓을 생성 : 내 컴퓨터에 들어갈 때는 localhost 또는 127.0.0.1(루프백)
// 다른 컴퓨터에 들어갈 때에는 ip address
Socket client = null;
// 서버에서 보내오는 메시지를 읽기위한 스트림
DataInputStream dis = null;
try {
String ip = JOptionPane.showInputDialog(""
+ "서버 ip\n130,132.133.134,135,157,146"
+ ",131,141,142,143,144,155,146,148,149,151,152,153");
client = new Socket("000.00.00."+ip,3000);
System.out.println("서버에 접속 하였습니다. "+client);
// 소켓에서 스트림 얻기
dis = new DataInputStream(client.getInputStream());
// 서버에서 보내온 메시지 읽기
String revMsg = dis.readUTF();
JOptionPane.showMessageDialog(null, "서버의 메시지 : "+revMsg);
} finally {
if(client != null) client.close();
if(dis != null) dis.close();
}
}