본문 바로가기
교육/Java&Spring

kosta 클라우드 네이티브 애플리케이션 개발 과정 day 20

by Renechoi 2023. 1. 16.

강사님이 바뀌었다 

 

서창훈 -> 정종욱 

 


테스트 ! 

 

package kosta.basic.day020;

public class Base {
    public void service(String state) {

        if (state.equals("낮")) {
            day();
            return;
        }

        if (state.equals("오후")) {
            afterNoon();
            return;
        }

        if (state.equals("밤")) {
            night();
        }
    }

    private void night() {
        System.out.println("night");
    }

    private void day() {
        System.out.println("낮에는 열심히 일하자 !");
    }

    private void afterNoon() {
        System.out.println("오후도 낮과 마찬가지로 일해야 합니다.");
    }
}

 

 

네트워크 . . .? 

 

 

네트워크...

유/무선으로 연결 

1. Bluetooth, Wi-fi, Rfid, 적외선 통신 등 근거리 무선 통신

2. WCDMA, LTE 등과 같은 이동 통신 기술 

3. Ethernet, SErial 통신 등과 같은 유선 통신 

4. GPS 

 

 

 

디바이스 

1. 보통, 네트워크에 연결된 컴퓨터

2. 컴퓨터가 아닌 다른 Devices 

(프린터, 모바일 디바이스, 가전제품, 웨어러블 컴퓨터 등 다양한 임베디드 제품들) 

3. 포괄적 개념으로 네트워크에 연결되어 있는 것들을 총칭해서 디바이스라 할 수 있다. 

 

 

 

데이터 통신 방법 

- 두 개의 상이한 두 디바이스가 물리적으로 떨어져 있는 경우 유/무선을 통해 네트워크에 연결 

- 전류나 전파, 빛 등의 방식으로 데이터 통신

- byte 단위의 통신 

- 주소 : 서로의 위치를 알아야 함. 이 위치를 node라고 함. node마다 고유의 주소를 가지고 있어야 함. 

 

 

 

 

실제, 네트워크를 통한 통신을 할 때는 Packet을 사용하게 된다.

- header

- body 

 

 

인터넷의 이해 

인터넷 역사 

 

 

OSI 7 계층과 TCP/IP 4계층 

 

IPv4 = 4byte 주소체계 

IPv6 = 16byte 주소체계 

 

4Byte IP 주소는 Network 주소와 Host(호스트) 주소로 나뉜다. 

 

 

전송 계층(Transport Layer) 

- 하위 계층 Internet 계층의 IP가 해결한 목적지까지의 네트워크상의 경로에서 실제 데이터를 전송하는 역할

- TCP와 UDP 라는 데이터의 전달을 책임지는 프로토콜이 존재한다 

- IP는 하나의 Packet이 전달되는 과정에만 중심을 두고 설계 되었기 때문에 여러 Packet으로 나눠져 전달되는 데이터의 순서와 전송 자체는 신뢰할 수 없다

- 데이터의 순서와 신뢰할 수 있는 데이터 전송을 보장하는 역할을 전송 계층의 프로토콜이 맡는다. 

 

TCP를 전화 통화와 비교한다

TCP는 UDP에 비해 프로토콜이 더 복잡하고 속도도 느리다. 

UDP에 비해 데이터 전송이 가능하다는 장점 때문에 HTTP, FTP, TELNET 등 대부분 응용계층 프로토콜은 전송 계층으로 TCP를 이용한다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

포트 : 

16비트 정수를 사용한다 (0 - 65535) 

 

nslookup wwww.naver.com

 

 

 

 

 

자바가 Ip 주소를 얻는 방법 

 

IneatAddress ia = InetAddress.getLocalHost();

 

도메인의 이름을 통해 얻는 방법 

InetAddress ia = InetAddress.getByNames(String domainName);
InetAddress[] iaArr = InetAddress.getAllByNames(String domainName);

 

String ip = InetAddress.getHostAddress(); 

 

 

 

 

 

Tcp 서버를 연결해서 

 

localhost를 통해 요청 보내보기 

 

package kosta.basic.day020.localHost;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {

    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind( new InetSocketAddress("Localhost", 10010));
            System.out.println("[서버] 연결 기다림");
            Socket socket = serverSocket.accept();
            System.out.println("[서버] 연결됨");

            InetSocketAddress inetSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
            System.out.println("서버 연결됨 " + inetSocketAddress.getHostName() + ":" + inetSocketAddress.getPort());

            OutputStream outputStream = socket.getOutputStream();
            String data = "Hello world\n";
            outputStream.write(data.getBytes("UTF-8"));
            outputStream.flush();
            outputStream.close();




        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(serverSocket != null && !serverSocket.isClosed()) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

 

 

 

 


 

 

 

리눅스/유닉스를 배워야 하는 이유 

 

윈도우 => 업데이트를 한다 

=> 그러면 재부팅을 해야 한다 

 

 

 

에코 서버 

 

package kosta.basic.day020.localHost;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;

public class EchoClient {

    private static final String ServerIP = "localhost";
    private static final int PORT = 10001;

    public static void main(String[] args) {
        Socket socket = null;
        Scanner sc = new Scanner(System.in);

        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(ServerIP, PORT));

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream());

            while (true) {
                System.out.print("<-");
                String request = sc.nextLine();

                if (request == null) {
                    System.out.println("접속 종료");
                    break;
                } else {
                    printWriter.print(request + "\n");
                    printWriter.flush();
                    System.out.println("->" + bufferedReader.readLine());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null && !socket.isClosed()) {
                try {
                    socket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

 

 

에코 : 클라이언트가 서버에 메시지 보내고 그대로 되돌아오는 

 

 

 

 

에코서버와 TCPServer에서 스트링 추가시 정상 입력이 안되는 문제 

 

 

 


문제는 입력시 개행문자("\n")이 찍혀서 함께 바이트 배열에 저장이 되었기 때문. outputStream에서 읽을 때 개행문자를 기준으로 읽는다. 그래서 해당 값 이전까지만 읽고 이미 생성된 이후에 추가된 "!!!"메시지는 다음 버퍼로 넘어가서 대기 상태로 존재하고 그렇기 때문에 다음 출력 때 함께 출력이 되는 것을 확인했다. 

결국 바이트 배열로 추가되어야 할 값이 있다면 
1) 저장되기 이전에 들어가거나
2) 이미 저장이 되었다면 배열을 분해해서 다시 삽입 알고리즘으로 넣어주어야 
하는 상황이라고 판단. 

관련 내용으로 편하게 구현된 메서드가 있을 것 같아 찾아보았는데 찾기 힘들었다.

그래서 그냥 어설프게라도 구현을 직접 해보았다. 

 

근데... 진짜 메서드가 없을까? 설마.. 

 

 

 

 

오리지널 코드 

 

package kosta.basic.day020.localHost;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;

public class TCPServer7Original {


    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress("localhost", 10001));
            System.out.println("[서버] 연결 기다림");
            Socket socket = serverSocket.accept();

            InetSocketAddress inetSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
            System.out.println("[서버] 연결됨 from " +
                    inetSocketAddress.getHostName() + ":" +
                    inetSocketAddress.getPort());
            // 데이터 보내기
            OutputStream outputStream = socket.getOutputStream();
//      String data = "채팅서버 접속을 환영합니다 \n";
//      os.write( data.getBytes( "UTF-8" ) );
//      os.flush();

            // 데이터 받기
            InputStream inputStream = socket.getInputStream();
            while (true) {
                byte[] buffer = new byte[128];
                int readByteCount = inputStream.read(buffer);
                System.out.println(Arrays.toString(buffer));

                if (readByteCount < 0) {
                    System.out.println("[서버] 클라이언트로 부터 연결끊김");
                    break;
                }
                String dataReceived = new String(buffer, 0, readByteCount, "UTF-8");
                System.out.println("[서버] 데이터 수신 : " + dataReceived);

                if (dataReceived.equalsIgnoreCase("exit")) {
                    System.out.println("[서버] 클라이언트로 통신 종료 요청");
                    break;
                }

                String addMessage = "!!!";
                dataReceived += addMessage;
                System.out.println(Arrays.toString(dataReceived.getBytes("UTF-8")));
                outputStream.write(dataReceived.getBytes("UTF-8"));

            }

            outputStream.close();
            inputStream.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null && !serverSocket.isClosed()) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private static byte[] addValue(byte[] buffer,  int readByteCount, String value) throws IOException {
        if (value.isEmpty() || value.isBlank()){
            return buffer;
        }
        List<Integer> temporalList = new ArrayList<>();
        IntStream.range(0, readByteCount + value.length())
                .filter(i -> buffer[i] != 10)
                .forEach(i -> {
                    Runnable addFunction = i < readByteCount ?
                            () -> temporalList.add((int) buffer[i]) :
                            () -> temporalList.add((int) value.getBytes()[i-readByteCount]);
                    addFunction.run();
                });

        byte[] newBuffer = new byte[temporalList.size()+1];
        IntStream.range(0, temporalList.size()).forEach(i -> newBuffer[i] = temporalList.get(i).byteValue());
        newBuffer[temporalList.size()] = 10;
        return newBuffer;
    }
}

 

 

 

입력 추가 로직 구현 코드 

 

package kosta.basic.day020.localHost;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class TCPServer7 {


    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress("localhost", 10001));
            System.out.println("[서버] 연결 기다림");
            Socket socket = serverSocket.accept();

            InetSocketAddress inetSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
            System.out.println("[서버] 연결됨 from " +
                    inetSocketAddress.getHostName() + ":" +
                    inetSocketAddress.getPort());
            // 데이터 보내기
            OutputStream outputStream = socket.getOutputStream();
//      String data = "채팅서버 접속을 환영합니다 \n";
//      os.write( data.getBytes( "UTF-8" ) );
//      os.flush();

            // 데이터 받기
            InputStream inputStream = socket.getInputStream();
            while (true) {
                byte[] buffer = new byte[128];

                int readByteCount = inputStream.read(buffer);
                String addMessage = "!!!";
                buffer = addValue(buffer, readByteCount, addMessage);

                if (readByteCount < 0) {
                    System.out.println("[서버] 클라이언트로 부터 연결끊김");
                    break;
                }
                String dataReceived = new String(buffer, 0, readByteCount + addMessage.length(), "UTF-8");
                System.out.println("[서버] 데이터 수신 : " + dataReceived);

                if (dataReceived.equalsIgnoreCase("exit")) {
                    System.out.println("[서버] 클라이언트로 통신 종료 요청");
                    break;
                }

                outputStream.write(dataReceived.getBytes("UTF-8"));

            }

            outputStream.close();
            inputStream.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null && !serverSocket.isClosed()) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private static byte[] addValue(byte[] buffer, int readByteCount, String value) throws IOException {
        if (value.isEmpty() || value.isBlank()) {
            return buffer;
        }
        List<Integer> temporalList = new ArrayList<>();
        IntStream.range(0, readByteCount + value.length())
                .filter(i -> buffer[i] != 10)
                .forEach(i -> {
                    Runnable addFunction = i < readByteCount ?
                            () -> temporalList.add((int) buffer[i]) :
                            () -> temporalList.add((int) value.getBytes()[i - readByteCount]);
                    addFunction.run();
                });

        byte[] newBuffer = new byte[temporalList.size() + 1];
        IntStream.range(0, temporalList.size()).forEach(i -> newBuffer[i] = temporalList.get(i).byteValue());
        newBuffer[temporalList.size()] = 10;
        return newBuffer;
    }
}
반응형