프로그래밍/java

JAVA 프로그래밍 56일차 (25/2/5)

wkun 2025. 2. 5. 14:54

contents

 

chapter 14

1.Network programming

1)네트워크와 네크워크 프로그래밍

2.클라이언트(Client)/ 서버(Server)

1)클라이언트와 서버

3.IP주소

1)IP주소란?

4.소켓 프로그래밍 TCP와 UDP

1)소켓 프로그래밍

2)TCP 소켓 프로그래밍

3)UDT 소켓 프로그래밍

 

 

----------------------------------------------------------

 

chapter 14

 

1.Network programming

-네트워크 프로그래밍은 다른 컴퓨터와 통신을 할 수 있는 프로그램을 작성하는 것임

 

1)네트워크와 네크워크 프로그래밍

-네트워크(Network)는 분산되어 있는 두 개 이상의 컴퓨터를 통신망으로 연결한 것을 말함. 즉 네크워크 프로그래밍이란 다른 컴퓨터와 송수신할 수 있는 프로그램을 만드는 것을 말함. 자바는 네트워크 프로그래밍에 필요한 대부분을 객체화하였기 때문에 사용자는 네트워크 어플리케이션의 통신 부분을 쉽게 프로그래밍할 수 있으며 고수준의 통신 프로그램을 만들 수 있음

 

2.클라이언트(Client)/ 서버(Server)

-클라이언트는 서비스를 요청하는 프로그램이고, 서버는 그 요청에 응답하는 프로그램임

 

1)클라이언트와 서버

-클라이언트(Client)란 서비스를 사용하는 컴퓨터를 말함. 반대로 서버(Server)는 서비스를 제공하는 컴퓨터임. 즉 일반적으로 우리들이 접속하는 사이트를 웹 서버라고 하고 우리들이 사이트에 접속하기 위해 사용하는 개인 컴퓨터를 클라이언트라고 함. 서버는 다수의 클라이언트를 위해 존재하기 때문에 일반적으로 매우 큰 용량과 성능을 가짐

 

3.IP주소

-IP주소는 컴퓨터와 네트워크에서 장치들이 서로를 인식하고 통신을 하기 위해 컴퓨터마다 부여되는 고유한 주소임

 

1)IP주소란?

-IP주소(Internet Protocal address)는 우리가 사용하는 일반적인 집 주소처럼 컴퓨터 네트워크에서 장치들이 서로를 인식하고 통신하기 위한 특수한 번호힘. 인터넷에 연결된 모든 컴퓨터는 4byte(32bit)의 정수로 구성된 IP 주소를 가지며 '123.456.789.123'와 같은 형식으로 표현됨

-자신의 IP 주소를 알아보려면 윈도우-실행탭에서 cmd를 우선 실행함. 그리고 까만색 화면이 나타나면 'ipconfig'라고 입력함. 콘솔에 결과 값이 표시되는데 여기서 IPv4 주소에 해당하는 192.168.10.143이 현재 사용하는 컴퓨터의 IP주소임

무선 LAN 어댑터 Wi-Fi:
   연결별 DNS 접미사. . . . :
   링크-로컬 IPv6 주소 . . . . : fe80::f435:805f:36d:4eec%2
   IPv4 주소 . . . . . . . . . : 192.168.10.143
   서브넷 마스크 . . . . . . . : 255.255.0.0
   기본 게이트웨이 . . . . . . : 192.169.10.1

 

-IP 주소는 공통으로 사용하는 네크워크 주소와 개인별로 할당되는 호스트 주소로 이루어져 있음

IP주소 = 네트워크주소 + 호스트 주소

 

-IP주소 중에서 네트워크 주소와 호스트 주소가 차지하는 bit의 수는 네크워크 구성에 따라 매번 달라짐. 지금 출력된 IP 값에서 네크워크 주소 값을 알아보기 위해서 IP 주소에 서브넷 마스크값인 255.255.255.0을 & 연산을 함

 -그러면 기본 게이트웨이 값인 192.168.10.1이 나오게 되는데 이 주소가 바로 네크워크 주소임. 만약 다른 호스트의 네트워크 주소 값을 계산하였는데 그 값이 같다면 두 호스트가 같은 네크워크 안에 포함되어 있다는 의미임. 그리고 네크워크 주소를 제외한 마지막 8bit 값인 143이 호스트 주소가 됨

-자바에서는 이 IP주소를 다루는데 이용할 수 있는 InetAddress 클래스가 있음

메서드 설명
byte[] getAddress() IP주소를 byte주소로 반환함
static InetAddress[]
getAllByName(String host)
도메인명에 지정된 모든 호스트의 IP 주소를 배열에 담아 반환함
static InetAddress
getByName(String host)
도메인명을 통해 IP주소를 얻음
String getHostAddress() 호스트의 IP 주소를 반환함
String getHostName() 호스트의 이름을 반환함
boolean isMulticastAddress() IP주소가 멀티캐스트 주소인지 확인함
boolean isLoopbackAddress() IP주소가 loopback 주소인지 알려줌

 

<현재 컴퓨터의 IP주소와 이름을 확인하는 프로그램>

package ch15;


import java.net.*;
public class exam108 {


public static void main(String[] args) {
InetAddress ip = null;
try {
//예외처리
ip = InetAddress.getLocalHost();
//호스트의 이름을 출력합니다.
System.out.println("getHostName():" + ip.getHostName());
//호스트의 주소를 출력합니다.
System.out.println("getHostAddress():" + ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}


}


}

 

실행 결과

getHostName():DESKTOP-IQHJ0B5
getHostAddress():172.16.7.114

 

-결과 값에서 getHostAddress() 메서드를 통해 반환된 값을 보면 이전에 ipconfig 명령어를 통해 확인했던 IP 주소와 동일한 것을 확인함

package ch15;


import java.net.*;
public class exam109 {


public static void main(String[] args) {
InetAddress ip = null;

try {
ip = InetAddress.getByName("www.daum.com");
System.out.println("getHostName():" + ip.getHostName());
System.out.println("getHostAddress():" + ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}

try {
ip = InetAddress.getByName("www.naver.com");
System.out.println("getHostName():" + ip.getHostName());
System.out.println("getHostAddress():" + ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}

try {
ip = InetAddress.getByName("www.eieifemiofmeowfmwe.com");
System.out.println("getHostName():" + ip.getHostName());
System.out.println("getHostAddress():" + ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
/*
try {
ip = InetAddress.getLocalHost();
System.out.println("getHostName():" + ip.getHostName());
System.out.println("getHostAddress():" + ip.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}*/


}


}

 

실행 결과

getHostName():www.daum.com
getHostAddress():148.66.138.196
getHostName():www.naver.com
getHostAddress():223.130.192.248
java.net.UnknownHostException: 알려진 호스트가 없습니다 (www.eieifemiofmeowfmwe.com)
at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:933)
at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1543)
at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:852)
at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1532)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1384)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1305)
at java.base/java.net.InetAddress.getByName(InetAddress.java:1255)
at ch15.exam109.main(exam109.java:26)

 

-InetAddress의 메서드를 활용하여 www.daum.com(다음), www.naver.com(네이버),http://www.eieifemiofmeowfmwe.com/의 의 호스트네임과 주소를 알아보는 코드임 

-여기서 마지막 주소인 http://www.eieifemiofmeowfmwe.com 주소는 임의의  주소로 실제 존재하지 않는 주소임. 결과 값을 보면 다음과 네이버의 호스트네임과 IP주소는 잘 반환 되었고 마지막 주소의 값은 UnknownHostException에 의해 예외처리 때문에 에러 문구를 출력한 것을 확인함

 

4.소켓 프로그래밍 TCP와 UDP

-소켓을 이용하여 통신을 하는 방식에는 TCP와 UDP가 있음

 

1)소켓 프로그래밍

-소켓 프로그래밍이란 소켓을 이용한 통신을 하는 프로그램을 작성하는 것을 말함. 소켓(Socket)이란 프로세스간의 통신에 사용되는 양쪽 끝단(endpoint)을 의미하는데 이는 네트워크상에서 서버, 클라이언트 두 개의 프로그램이 특정 포트를 통해 양방향 통신이 가능하도록 만들어주는 장치임

-포트(port)는 가상의 통신 선로임. 하나의 컴퓨터 안에는 여러 개의 프로세스가 수행되고 있으므로 특정한 응용프로그램과 통신하기 위해서는 그 응용프로그램으로 통하는 선로가 필요한데 이를 포트라고 함. 포트 번호는 0부터 65535까지의 번호를 사용하지만 1023아래의 포트는 기존 다른 통신 프로그램이 사용하는 경우가 많기 때문에 1023번 이상의 숫자에서 사용하는 것이 좋음

-TCP와 UDP는 각각 다른 방식의 소켓프로그래밍을 의미함. 연결방식과 전속방식에서 차이가 있음

항목 TCP UDP
연결방식 -연결 후 통신(3way-handshake)
-1:1 통신방식
-연결하지 않고 통신
-1:1부터 n:n 통신방식
특징 -데이터의 전송순서가 보장
-데이터의 수신여부 확인
-UDP보다 느림
xe)로그인: 정확해야함
-데이터의 전송순서 보장되지 않음
-순서가 바뀔 수 있음
-데이터의 수신여부 확인안함
-TCP보다 속도가 빠름
ex)실시간 동영상, 게임 

 

-TCP방식은 전화와 비슷하고 UDP방식은 소포와 비슷함. TCP는 서로 간에 연결이 확인된 후 통신이 가능한 점에서 전화와 같고 UDP는 연결이 되어있는지 여부는 중요하지 않고 데이터를 전송하므로 소포와 비슷함. 또한 UDP는 데이터의 순서를 확인하거나 바르게 수신되었는지 확인하는 과정을 거치지 않기 때문에 전송이 빠르다는 장점이 있음

 

2)TCP 소켓 프로그래밍

-TCP 소켓 프로그래밍은 서버와 클라이언트의 일대일 통신이기 때문에 서버가 실행되고 클라이언트의 연결을 기다림. 통신과정은 다음과 같음

1.서버 쪽에서는 서버소켓을 특정 포트와 결합하여 클라이언트의 요청을 기다림
2.클라이언트 쪽에서는 소켓을 생성하여 서버의 IP주소와 연결할 포트를 가지고 서버에 연결을 요청함
3.서버소켓은 클라이언트로부터 연결 요청을 받으면 서버 쪽에 새로운 소캣을 생성해서 클라이언트의 소켓과 연결함
4.클라이언트와 서버의 소켓이 연결되었으므로 서로 간의 통신이 가능해 짐 

 

-서버 쪽에서는 서버소켓(ServerSocket)과 일반적인 소켓 두 가지가 있는데 여기서 서버소켓은 단순히 클라이언트의 연결요청을 받아서 일반적인 소켓과 클라이언트의 소켓을 연결해주는 역할만을 함. 실제 통신은 서버 쪽의 소켓과 클라이언트의 소켓사이에서 이루어짐

·소켓(Socket):
-프로세스간의 통신을 하며 InputStream과 OutputStream을 가지고 있음. 이 스트림을 통해서 통신이 이루어 짐
·서버소켓(ServerSocket)
-포트와 연결(bind)되어 클라이언트의 연결을 기다리다가 연결이 되면 Socket을 생성해서 소켓끼리 연결되게 함
package ch15;


//서버 프로그램
import java.net.*;
import java.io.*;


public class exam110 {


public static void main(String[] args) {
ServerSocket serverSocket = null;


try {
/// 포트 8000번에 bind
serverSocket = new ServerSocket(8000);
System.out.println("서버가 준비되었습니다.");
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
System.out.println("연결 요청을 기다리는 중...");
// 연결 요청이 들어오면 accept로 허용
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress() + "연결 요청이 들어왔습니다.");
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeUTF("TEST 확인");
System.out.println("메시지를 전송합니다.");
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


}

 

실행 결과

서버가 준비되었습니다.
연결 요청을 기다리는 중...
/172.16.1.80 연결 요청이 들어왔습니다.
메시지를 전송합니다.
연결 요청을 기다리는 중...

 

-위의 실행 결과는 cmd 콘솔 창을 실행한 다음 한 쪽에서는 서버프로그램을, 한쪽에서는 클라이언트 프로그램을 실행해서 통신을 확인한 결과 화면임. 서버가 통신하기 까지의 과정은 다음과 같음

1.ServerSocket을 생성하고 8000번 포트에 연결(bind)함

serverSocket = new ServerSocket(8000);

2.클라이언트로부터 연결이 올 때까지 계속해서 이 상태로 기다림. 만약 이 상태에서 클라이언트로부터 연결이 확인(accep)되면 서버소켓은 다른 소켓을 생성해서 클라이언트와 연결함

Socket socket = serverSocket.accept();

 

3.OutputStream을 통해서 "TEST확인"이라는 메시지를 클라이언트에게 전송함

OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeUTF("TEST 확인");

 

4.사용이 완료된 소켓과 스트림은 종료시켜줌. 그리고 다시 서버소켓은 클라이언트의 연결을 기다림

dos.close();
socket.close();

 

<서버프로그램과 통신하는 클라이언트 프로그램>

package ch15;


//클라이언트 프로그램
import java.net.*;
import java.io.*;


public class exam111 {


public static void main(String[] args) {
try {
String serverIp = "172.16.1.80";
System.out.println("서버에 연결을 시도하는 중...");

//포트 번호 8000과 serverIP을 가지고 접속을 시도
Socket socket = new Socket(serverIp, 8000);
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
System.out.println("서버로부터 받은 메시지:" + dis.readUTF());
dis.close();
socket.close();
System.out.println("연결이 종료되었습니다.");
} catch (ConnectException ce) {
ce.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}

}


}

 

실행 결과

서버에 연결을 시도하는 중...
서버로부터 받은 메시지:TEST 확인
연결이 종료되었습니다.

 

-서버로부터 "TEST확인"이라는 메시지를 받고 연결이 종료됨.

1.IP와 서버의 포트 번호인 8000과 통신하기 위해 소켓을 생성함. 생성과 동시에 자동으로 해당 서버 소켓에 연결을 시도하게 됨. 만약 서버 프로그램이 먼저 실행되고 있지 않았다면 ConnetException이 발생함.

String serverIp = "172.16.1.80";
Socket socket = new Socket(serverIp, 8000);

 

2.소켓의 InputStream을 통해 서버로부터 메시지를 받고 출력함

InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
System.out.println("서버로부터 받은 메시지:" + dis.readUTF());

 

3.사용한 소켓과 스트림은 닫음

dis.close();
socket.close();

 

3)UDT 소켓 프로그래밍

-UDP 소켓 프로그래밍은 DatagramSocket과 DatagramPacket을 사용함. TCP처럼 연결이 확인된 후에 데이터를 전송하는 것이 아니기 때문에 따로 서버소켓이 필요하지는 않으며 DatagramSocket을 통해 접속을 요청하면 데이터를 DatagramPacket에 담아서 전송함