2021. 12. 24. 14:27ㆍ자바/자바의 정석
배운 것
네트워킹에 대한 개략적인 이해
자바에서 ip주소, URL을 다룰 수 있다는 것
소켓 프로그래밍을 통해 통신이 가능하다는 것
내용 정리
네트워킹
- 두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것
- 컴퓨터들을 서로 연결하여 데이터를 손쉽게 주고받고 자원을 공유하는 것
- java.net패키지를 사용해 네트워크 어플리케이션의 데이터 통신 부분을 쉽게 작성 가능
서버
- 서비스를 제공하는 컴퓨터
- 일반적으로 서버는 다수의 클라이언트들에게 서비스를 제공
- 서버가 제공하는 서비스의 종류에 따라 파일 서버, 메일 서버, 어플리케이션 서버등이 존재
클라이언트
- 서비스를 사용하는 컴퓨터
서비스
- 서버가 클라이언트로부터 요청받은 작업을 처리하여 그 결과를 제공하는 것
서버가 서비스를 사용하기 위해서는 서버 프로그램이 있어야 하고,
클라이언트가 서비스를 제공받기 위해서는 서버 프로그램과 연결할 수 있는 클라이언트 프로그램이 있어야 함
ex) 웹서버-웹브라우저
네트워크를 구성할 때 전용서버를 두는 것을 서버기반모델
별도의 전용서버없이 각 클라이언트가 서버역할을 동시에 수행하는 것을 P2P모델
IP주소
- 컴퓨터(호스트)를 구별하는데 사용되는 고유한 값
- 인터넷에 연결된 모든 컴퓨터는 IP주소를 갖는다
네트워크 주소 / 호스트 주소
- IP주소와 서브넷 마스크를 비트연산자 '&'로 연산해 IP주소에서 네트워크 주소를 알아낼 수 있음
- 네트워크주소가 차지하는 자리수가 많을수록 호스트 주소의 범위가 줄어듦
- 호스트 주소가 0인 것은 네트워크 자신을 나타내고, 255는 브로드캐스트 주소로 사용됨
- 실제로 네트워크에 포함 가능한 호스트 개수는 254개
InetAddress
- 자바에서 IP주소를 다루기 위한 클래스
public class Ex16_1 {
public static void main(String[] args) {
// IP주소를 다루기 위한 클래스
InetAddress ip = null;
InetAddress[] ipArr = null;
try {
ip = InetAddress.getByName("www.google.com");
System.out.println(ip.getHostName());
System.out.println(ip.getHostAddress());
System.out.println(ip.toString());
byte[] ipAddr = ip.getAddress();
System.out.println(Arrays.toString(ipAddr));
String result = "";
for(int i=0; i<ipAddr.length; i++) {
result += (ipAddr[i] < 0 ? ipAddr[i]+256 : ipAddr[i])+".";
}
System.out.println(result);
System.out.println();
ip = InetAddress.getLocalHost();
System.out.println(ip.getHostName());
System.out.println(ip.getHostAddress());
System.out.println();
ipArr = InetAddress.getAllByName("www.naver.com");
for(int i=0; i<ipArr.length; i++) {
System.out.println(i+". "+ipArr[i]);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
InetAddress클래스를 이용해 ip주소, 호스트 이름등을 알아 낼 수 있음
URL
- 인터넷에 존재하는 여러 서버들이 제공하는 자원에 접근할 수 있는 주소를 표현하기 위한 것
- '프로토콜://호스트명:포트번호/경로명/파일명?쿼리스트링#참조'
- 자바에서 URL을 다루기 위한 클래스
public class Ex16_2 {
public static void main(String[] args) throws Exception {
// URL객체 생성
URL url = new URL("https://tree-19.tistory.com/");
System.out.println(url.getAuthority());
System.out.println(url.getContent());
System.out.println(url.getDefaultPort());
System.out.println(url.getPort());
System.out.println(url.getFile());
System.out.println(url.getHost());
System.out.println(url.getProtocol());
System.out.println(url.getQuery());
System.out.println(url.getRef());
System.out.println(url.getUserInfo());
System.out.println(url.toExternalForm());
System.out.println(url.toURI());
}
}
URL클래스를 이용해 파일명, 호스트명, 경로명, 포트명등을 알 수 있음
URLConnection
- 어플리케이션과 URL간의 통신연결을 나타내는 클래스의 최상위 클래스, 추상클래스
public class Ex16_4 {
public static void main(String[] args) {
URL url = null;
BufferedReader input = null;
String address = "https://tree-19.tistory.com";
String line="";
try {
url = new URL(address);
input = new BufferedReader(new InputStreamReader(url.openStream()));
while((line=input.readLine())!=null) {
System.out.println(line);
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
https://tree-19.tistory.com 주소의 내용을 URL클래스를 이용해 가져와서 콘솔에 한 줄씩 출력하는 예제
URLConnection클래스가 쓰이지 않았다.
어떻게 연결이 되어서 해당 ip주소의 정보를 출력할 수 있었을까?
InputStream in = url.openStream();
openStream()은 openConnection()을 호출해서 URLConnection을 얻은 다음 여기에 다시 getInputStream()을 호출한 것과 같다.
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();
public class Ex16_5 {
public static void main(String[] args) {
URL url = null;
InputStream in = null;
FileOutputStream out = null;
String address = "https://tree-19.tistory.com";
int ch=0;
try {
url = new URL(address);
in = url.openStream();
out = new FileOutputStream("tistory.txt");
while((ch=in.read())!=-1) {
out.write(ch);
}
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
위와 동일한 예제이지만, 이번엔 콘솔에 출력하지 않고 tistory.txt파일에 쓰는(write) 예제이다.
소켓
- 프로세스간의 통신에 사용되는 양쪽 끝단(endpoint)
- 서로 멀리 떨어진 두 사람이 통신하기 위해 전화기가 필요한 것처럼, 프로세스간의 통신을 위해서 필요한 것이 소켓
소켓 프로그래밍
- 소켓을 이용한 통신 프로그래밍
- java.net패키지를 통해 지원
TCP/IP 프로토콜
- 이기종 시스템간의 통신을 위한 표준 프로토콜
- TCP/UDP가 포함
항목 | TCP | UDP |
연결방식 | 연결기반 연결 후 통신(전화기) 1:1통신방식 |
비연결기반 연결없이 통신(소포) 1:1, 1:N, N:N통신방식 |
특징 | 데이터의 경계를 구분안함 신뢰성 있는 데이터 전송 - 데이터의 전송순서 보장됨 - 데이터의 수신여부를 확인함 (데이터가 손실되면 재전송) - 패킷을 관리할 필요가 없음 UDP보다 전송속도 느림 |
데이터의 경계를 구분함 신뢰성 없는 데이터 전송 - 데이터의 전송순서 바뀔 수 있음 - 데이터의 수신여부 확인안함 (데이터가 손실되어도 알 수 없음) - 패킷을 관리해주어야 함 TCP보다 전송속도 빠름 |
관련 클래스 | Socket ServerSocket |
DatagramSocket DataramPacket MulticastSocket |
TCP소켓 프로그래밍
- 클라이언트와 서버간의 1:1 통신
통신 과정
1. 서버 프로그램에서 서버소켓을 사용해 서버 컴퓨터의 특정 포트에서 클라이언트의 연결요청 처리 준비
2. 클라이언트 프로그램은 접속할 서버의 IP주소, 포트 정보를 가지고 소켓을 생성해 서버에 연결 요청
3. 서버소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해 클라이언트 소켓과 연결
4. 클라이언트 소켓과 새로 생성된 서버의 소켓은 서버소켓관 관계없이 1:1통신
서버 소켓
- 포트와 결합(바인딩)되어 포트를 통해 원격 사용자의 연결요청을 기다리다가 연결요청이 올 때마다 새로운 소켓을 생성하여 상대편 소켓과 통신할 수 있도록 연결
- 소켓간의 연결만 처리, 실제 데이터는 소켓들끼리 주고 받음
public class TcpIpServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 서버소켓 생성, 7777번 포트와 결합(바인딩)
serverSocket = new ServerSocket(7777);
System.out.println(getTime()+"서버가 준비되었습니다.");
} catch (IOException e) {e.printStackTrace();}
while(true) {
try {
System.out.println(getTime()+"연결요청을 기다립니다.");
// 서버소켓은 클라이언트의 연결요청이 올 때 까지 실행을 멈추고 기다림
// 클라이언트의 요청이 오면 클라이언트 소켓과 통신할 새로운 소켓을 생성
Socket socket = serverSocket.accept();
System.out.println(getTime()+socket.getInetAddress()+"로부터 연결요청");
// 소켓의 출력스트림을 얻어옮
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 데이터를 보냄
dos.writeUTF("[Notice] Test Message1 from Server.");
System.out.println(getTime()+"데이터를 전송했습니다");
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static String getTime() {
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date());
}
}
서버소켓이 7777번 포트에서 클라인트 프로그램의 연결요처을 기다림
클라이언트 프로그램이 서버에 연결을 요청하면, 서버소켓은 새로운 소켓을 생성해 클라이언트 프로그램의 소켓과 연결
public class TcpIpClient {
public static void main(String[] args) {
try {
String serverIp = "127.0.0.1";
System.out.println("서버에 연결중입니다. 서버IP :"+ serverIp);
// 소켓을 생성해 연결 요청
Socket socket = new Socket(serverIp, 7777);
// 소켓의 입력스트림을 얻어옮
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
// 소켓으로부터 받은 데이터 출력
System.out.println("서버로부터 받은 메시지 :"+dis.readUTF());
System.out.println("연결 종료");
socket.close();
dis.close();
System.out.println("연결 종료");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
연결하고자 하는 서버의 IP와 포트번호를 가지고 소켓을 생성하면 자동적으로 서버에 연결을 요청
서버와 연결되면 소켓의 입력스트림을 얻어서 서버가 전송한 데이터를 읽음
느낀 점/보완할 점
익숙치 않은 부분이라 아직 제대로 이해되지 않은 것 같다
가볍게 익혀두고 필요할 때 더 공부해야겠다
잘못된 정보가 있다면 지적 부탁드려요
'자바 > 자바의 정석' 카테고리의 다른 글
자바의 정석 2장 변수 (0) | 2021.12.27 |
---|---|
자바의 정석 15장 입출력 (0) | 2021.12.23 |
13장 쓰레드 20200106 (0) | 2021.01.06 |
13장 쓰레드 20210104 (0) | 2021.01.04 |
13장 Thread 20201120 (0) | 2020.11.20 |