1. 네트워킹이란?
두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것
* 자바에서는 java.net 패키지를 활용해 네트워크 어플의 데이터 통신을 쉽게 작성 가능하다.
https://www.youtube.com/watch?v=yR4hnj5XNP4&t=5s
[참조 : OSI 7 계층, TCP 4 layer] https://velog.io/@dyllis/OSI-7%EA%B3%84%EC%B8%B5-%EC%A0%95%EB%A6%AC - OSI 7계층 : 물리계층 - > 데이타 링크 계층/ -> 네트워크계층/ -> 전송계층 / -> 세션 계층 -> 표현 계층 -> 응용계층 |
2. 클라이언트와 서버
* 서비스란? 서버가 클라이언트로부터 요청받은 작업을 처리하여 그 결과를 제공하는 것
- 클라이언트와 서버와의 관계
클라이언트 | <-> | 서버 |
[1] 연결을 요청 [3] 처리 요청 |
[2] 연결 수락 [4] 처리/응답 (서비스 제공) |
- 서버의 모델
명칭 | 서버 기반 모델 (server-based model) | P2P모델(peer-to-peer model) |
내용 | 전용 서버를 둠 | 전용 서버 없이 각 클라이언트가 서버역할 동시수행 |
장/단점 | - 안정적인 서비스 제공 가능 - 공유데이터의 관리와 보완이 용이 - 서버 구축 비용과 관리 비용이 든다. |
- 서버 구축 및 운용비용을 절감 가능 - 자원의 활용을 극대화 가능 - 자원의 관리가 어려움 - 보안이 취약 |
3. IP주소 : "내 컴퓨터"를 나타내는 주소.
https://www.youtube.com/watch?v=IAS3U5ZiI8c
- 4byte로 0~255사이로 표현 (ex. 255.255.255.0)
- 앞의 3byte는 네트워크 주소 + 뒤 1byte는 호스트 주소
- 명령프롬프트에서 "ipconfig/All" 또는 "ipconfig"를 치면 확인 가능
3-1. java.net패키지의 InetAddress클래스
[1] 로컬 컴퓨터에서 IP 주소 얻으려 할 때
//객체 생성
InetAddress ip = InetAddres.getLocalHost();
//객체 이름, 주소 추출 : String으로 반환
String ipName = ip.getHostName();
String ipAddress = ip.getHostAddress();
[2] 도메인 이름으로 IP 주소 얻으려 할때
//도메인에서 단일 ip 주소 가져오기
InetAddress ip = InetAddress.getByName("www.naver.com");
//도메인에서 여러개의 ip주소 가져오기
InetAddress[] ipArr = InetAddress.getAllByName("www.naver.com");
4. URL(Uniform Resource Locator)
- 형태 : 프로토콜://호트스명:포트번호/경로명/파일명?쿼리스트링#참조
- 예시 ) http://www.naver.com:80/sample/hello.html?refer=codechobo#index1
프로토콜 | 서버와 통신할 때 사용되는 통신규약(HTTP) |
호스트명 | 자원을 제공하는 서버명(ex.www.naver.com) |
포트번호 | 통신에서 사용되는 서버의 포트 번호 |
경로명 | 경로 |
파일명 | 파일명 (ex. index.html) |
쿼리 | URL에서 ? 이후의 부분 |
참조 | URL에서 # 이후의 부분 |
※ Filezilla에서 보는 호스트와 포트, 사용자명 개념
→ 호스트 : 도메인을 작성하거나, ip주소를 작성하는 공간
→ 사용자명 : 해당 호스트 사용자명 (보통 회사에서 지정해주는 게 있다.)
→ 비밀번호 : 접속 시 비밀번호
→ 포트 : 통신에서 사용되는 서버의 포트 번호 (일반적으로 FTP포트는 21이 가장 많다)
5. 소켓 프로그래밍
[1] 소켓에 대하여
- 소켓이란?
프로세스 간의 통신에 사용되는 양쪽 끝단으로
네트워크 기능(OS의 네트워크 라이브러리)을 용이하게 이용하기 위한 각 언어별 모듈(객체)이다.
- 모든 소켓은 각각 자신만의 InputStream, OutputStream을 가지고 있다.
- JVM은 각 운영체제별로 다르게 작동하며, 각 운영체제의 네트워크 라이브러리에 맞춘 소켓을 사용한다.
[2] 포트란?
- 같은 컴퓨터 내에서 프로그램을 식별하는 번호
- 0~65535 범위 (총 65536개) 값을 가질 수 있다.
- 세 가지 범위로 구분
(1) Well Known : 0~1023, ICANN가 애플리케이션용으로 미리 예약한 포트로 FTP, Telnet 등에서 사용
(2) Registed : 1024~49151, 회사에서 등록해서 사용 가능한 포트값
(3) Dynamic or Private : 49152~65535, 운영체제가 부여하는 동적 포트 또는 개인 목적의 포트
6. TCP와 UDP 프로토콜
- 클라이언트와 서버를 연결하는 프로토콜에는 여러가지 종류가 있다.
- TCP,UDP 외에도 통신 프로토콜로 HTTP 등이 있다.
항목 | TCP | UDP |
연결방식 | 연결기반 - 연결 후 통신(전화기) |
비연결기반 - 연결 없이 통신 (소포) |
특징 | 데이터의 경계를 구분 안함 (바이트스트림) 신뢰성 높은 데이터 전송 - 데이터의 전송순서가 보장됨 - 데이터의 수신여부를 확인함 (데이터가 손실되면 재전송됨) - 패킷을 관리할 필요가 없음 UDP보다 전송속도가 느림 데이터 전송용량의 제한이 없음 |
데이터의 경계를 구분함(datagram) 신뢰성 낮은 데이터 전송 - 데이터의 전송순서가 바뀔 수 있음 - 데이터의 수신여부를 확인안함 (데이터가 손실되어도 알 수 없음) - 패킷을 관리해주어야 함 TCP보다 전송 속도가 빠름 1회 전송량 512byte |
관련 클래스 | Socket ServerSocket |
DatagramSocket DatagramPacket MulticastSocket |
통신 방식 | Uni-cast (1:1) | BroadCast(불특정 다수) - local broadcast pf. xxx.xxx.xxx.255 로 일괄 전달 - global broadcast pf. 255.255.255.255 로 일괄 전달 MultiCast(특정 다수) pf. 회원 가입 대상자들만 전달 pf. 224.0.0.1 ~ 239.255.255.255 |
[참고]
유니캐스트 VS 브로드캐스트 VS 멀티캐스트 https://m.blog.naver.com/wnrjsxo/221250742423 |
7. TCP 소켓 프로그래밍
- "이것이 자바다" 영상의 아래 그림이 TCP를 이해하는데 많은 도움을 주는 것 같다.
[1] 송신 방법
package tcpProtocol;
import java.io.OutputStream;
import java.net.Socket;
public class BasicSend {
public static void main(String[] args) throws Exception{
//[1] 소켓을 연다.(연결할 서버소켓의 주소와 포트를 작성)
Socket socket = new Socket("localhost",50000);
OutputStream os = socket.getOutputStream();
for(int i = 1; i <= 3; i++) {
//[2] 소켓의 OutputStream을 통해 byte단위의 데이터를 전송한다.
String data = "데이터"+i;
os.write(data.getBytes("UTF-8"));
}
os.flush();
//[3] 소켓 연결 끊기
//socket.close(); --> 의도적인 종료 : -1 값을 전달한다.
socket.close();
}
}
[2] 수신 방법
package tcpProtocol;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class BasicAccept {
public static void main(String[] args) throws Exception{
//[1] 서버 소켓을 연다.
ServerSocket serverSocket = new ServerSocket(50000);
try {
//[2] 소켓을 연다.
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
//무한 루프로 수신 대기
System.out.println("[수신 데이터]");
while(true) {
//[3] InputStream을 통해 바이트단위 데이터를 가져온다.
byte[] byteArr = new byte[300]; //한글 3byte->100자씩 읽을 것
int len = is.read(byteArr);
if(len == -1) break;
String data = new String(byteArr,0,len,"UTF-8");
//[4] 수신 data 콘솔에 출력
System.out.println(data);
}
} catch (IOException e) {
System.out.println("[연결 종료]");
}
}
}
[연습 예제_1] TCP 1:1 전송방식으로 로컬컴퓨터에서 에코메시지 전달하기
<Client>
package tcpProtocol;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
public class Client extends JFrame{
JTextArea textMonitor;
JTextField textInput;
JButton button;
Socket socket;
Client(){
/* Initial Window UI Design */
super("Chat for Client");
setLocation(300,300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
init_UiDesign();
pack();
/* TCP Socket Communication */
init_buttonAction();
init_socket();
}//end Client()
/////////////////////////////////////////////////////
/* TCP Socket Communication Method */
private void init_buttonAction() {
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String textMessage = String.format("[사용자] %s%n", textInput.getText().trim());
if(textMessage.isEmpty()) {
JOptionPane.showMessageDialog(textMonitor,"메세지를 입력하세요.");
return;
}else {
//textMonitor.append(textMessage);
echo_message();
textInput.setText("");
return;
}
}
});
}
private void init_socket() {
try {
socket = new Socket("localhost",50000);
} catch (UnknownHostException e) {
System.out.println("해당 호스트를 찾을 수 없습니다.");
} catch (IOException e) {
System.out.println("포트가 비정상적으로 닫혀있습니다.");
}
}
protected void echo_message() {
send_message();
receive_message();
}
private void send_message() {
//send Message to server
try {
OutputStream outStream = socket.getOutputStream();
String userMessage = String.format("[사용자] %s%n", textInput.getText().trim());
//append message to Monitor
textMonitor.append(userMessage);
outStream.write(userMessage.getBytes());
outStream.flush();
} catch (IOException e) {
System.out.println("전송에 오류가 발생했습니다.");
}
}
private void receive_message() {
//receive Message from server
try {
byte[] readBytes = new byte[300];
int readNum = socket.getInputStream().read(readBytes);
String echoedMessage = new String(readBytes,0,readNum);
//append message to Monitor
textMonitor.append(echoedMessage);
} catch (IOException e) {
System.out.println("수신에 오류가 발생했습니다.");
}
}
/* UI Design Method */
private void init_UiDesign() {
//textMonitor : where chat text reveals
textMonitor = new JTextArea();
textMonitor.setBackground(new Color(0x7BC4C4));
textMonitor.setEditable(false);
JScrollPane jsp = new JScrollPane(textMonitor);
textMonitor.setPreferredSize(new Dimension(300,200));
this.add(jsp);
//textInput : where user types texts & send
JPanel jpl = new JPanel(new BorderLayout());
textInput = new JTextField();
button = new JButton("전송");
jpl.add(textInput);
jpl.add(button,"East");
this.add(jpl,"South");
}
public static void main(String[] args) {
new Client();
}//end main
}
<Server>
package tcpProtocol;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.*;
public class Server extends JFrame{
JTextArea textMonitor;
JTextField textInput;
JButton button;
ServerSocket serverSocket;
Socket socket;
Server(){
/* Initial Window UI Design */
super("Chat for Server");
setLocation(300,300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
init_UiDesign();
pack();
/* TCP Socket Communication */
init_socket();
}//end Client()
/////////////////////////////////////////////////////
/* TCP Socket Communication Method */
private void init_socket() {
try {
serverSocket = new ServerSocket(50000);
socket = serverSocket.accept();
while(true) {
//receive Message from client
byte[] readBytes = new byte[300];
int readNum = socket.getInputStream().read(readBytes);
String[] userMessage = new String(readBytes,0,readNum).split("]");
//append message to Monitor
textMonitor.append(new String(readBytes,0,readNum));
//send Message to client
OutputStream outStream = socket.getOutputStream();
String echoedMessage = String.format("[에코]%s%n",userMessage[1]);
//append message to Monitor
textMonitor.append(echoedMessage);
outStream.write(echoedMessage.getBytes());
outStream.flush();
}
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
}
}
/* UI Design Method */
private void init_UiDesign() {
//textMonitor : where chat text reveals
textMonitor = new JTextArea();
textMonitor.setBackground(new Color(0x7BC4C4));
textMonitor.setEditable(false);
JScrollPane jsp = new JScrollPane(textMonitor);
textMonitor.setPreferredSize(new Dimension(300,200));
this.add(jsp);
//textInput : where user types texts & send
JPanel jpl = new JPanel(new BorderLayout());
textInput = new JTextField();
button = new JButton("전송");
jpl.add(textInput);
jpl.add(button,"East");
this.add(jpl,"South");
}
public static void main(String[] args) {
new Server();
}//end main
}
>>결과
8. UDP 소켓 프로그래밍
- UDP는 소포와 같이 서버소켓을 통한 연결 없이 수신, 송신만 가능한 형태이다.
- 통신 선로가 고정적이지 않음
- 데이터 손실이 발생 가능
- 대신 TCP보다는 빠르게 전송이 가능하다
[1] 송신하는 법
//송신하는 법
//[1] DatagramSocket를 연다.
DatagramSocket datagramSocket = new DatagramSocket();
//만약, multi-cast방식으로 전달할 경우,
//MulticastSocket multicastSocket = new MulticastSocket();
InetAddress ia = InetAddress.getByName("localhost"); //수신되는 곳의 주소
//[2] 전달할 데이터를 패킷으로 패킹한다.
String data = "전달 데이터";
byte[] byteArr = data.getBytes("UTF-8"); //UTF-8방식으로 바이트 변환
DatagramPacket packet = new DatagramPacket(
byteArr, byteArr.length,ia,포트번호
);
//[3] DatagramSocket을 통해 패킷을 전송한다.(바이트단위로 전송된다)
datagramSocket.send(packet);
//[4] DatagramSocket을 닫아준다.
datagramSocket.close();
[2] 수신하는 법
//수신하는 법
//[1] DatagramSocket을 연다.
DatagramSocket datagramSocket = new DatagramSocket(포트번호);
//[2] 패킷을 받을 배열과 길이를 지정한다.
DatagramPacket datagramPacket = new DatagramPacket(받은 배열을 저장할 바이트 배열,배열의 길이);
//[3] 패킷을 받는다.
datagramSocket.receive(datagramPacket);
//[4] 소켓을 닫는다.
datagramSocket.close();
[연습 예제_간단한 데이터 송수신]
<Client>
package udpProtocol;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) throws Exception{
//[1] 데이터그램 소켓으로 가야하는 곳을 지정
DatagramSocket datagramSocket = new DatagramSocket();
InetAddress ia = InetAddress.getByName("localhost");
for(int i = 1; i <= 3; i++) {
//[2] 데이터그램 패킷으로 데이터를 묶어둔다.
String data = "데이터"+i;
byte[] byteArr = data.getBytes("UTF-8");
DatagramPacket datagramPacket = new DatagramPacket(
byteArr, byteArr.length,ia,8000
);
//[3] 패킷을 소켓을 통해 전송한다.
datagramSocket.send(datagramPacket);
}//end for
//[4] 소켓을 닫는다.
datagramSocket.close();
}//end main
}
<Server>
package udpProtocol;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception{
//[1] 소켓을 연다.
DatagramSocket datagramSocket = new DatagramSocket(8000);
//[2] 패킷 단위로 데이터를 받는다.
//쓰레드를 형성해서 무한 루프로 데이터를 받는다.
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("수신 시작");
try {
while(true) {
DatagramPacket packet = new DatagramPacket(new byte[100],100);
datagramSocket.receive(packet);
String data = new String(packet.getData(),0,packet.getLength(),"UTF-8");
System.out.println("[받은 내용 : "+packet.getSocketAddress()+"]"+data);
}
} catch (IOException e) {
System.out.println("[수신 종료]");
}
}
};//end thread
thread.start();
Thread.sleep(10000);
datagramSocket.close();
}//end main
}
>> 수신 결과
수신 시작
[받은 내용 : /127.0.0.1:55273]데이터1
[받은 내용 : /127.0.0.1:55273]데이터2
[받은 내용 : /127.0.0.1:55273]데이터3
[수신 종료]
[참조]
- 자바의 정석, 남궁성 지음
- 이것이 자바다
- 코딩하는 거니
- 티스토리 블로그
- 그 외 : 국비지원 수업 내용 참조
'Language > Java' 카테고리의 다른 글
[자바_API] java.lang패키지와 유용한 클래스(1) (0) | 2022.04.08 |
---|---|
[자바_API] 입출력 I/O (0) | 2022.04.05 |
[자바의정석_복습] 예외처리 (0) | 2022.03.28 |
[자바_예제] 2차원 배열 _ 달팽이(snail) 배열 (0) | 2022.03.28 |
[자바_예제] 2차원 배열_로또 추첨 (0) | 2022.03.28 |