[F-lab 모각코 챌린지 39일차] TIL

JeongheeKim·2023년 7월 9일

TIL

목록 보기
39/66

학습계획


  • 자바 네트워크 프로그래밍
  • TCP, UDP 특징
  • Java7,8에서 달라진것들

Today I Learned


자바 네트워크 프로그래밍

  • TCP(Transfer Control Protocol)
    • HTTP, FTP, Telnet이 대표적인 TCP 통신
    • 연결 기반 프로토콜
    • 상대방이 데이터를 받았는지 응답을 확실히 보장한다.
      • 이 부분에 대한
  • UDP(User Datagram Protocol)
    • 상대방이 데이터를 받았는지에 대한 보장이 없다.
    • TFTP(네트워크 장비 펌웨어 업그레이드), SNMP(네트워크 모니터링, 경고 및 알림)

→ 모든 네트워크 통신을 정확한 TCP로 하면 될거같은데 왜 UDP를 쓸까?

TCP는 상대방에 대한 응답을 보장하지만, 이에 대한 처리 비용이 크고 데이터가 무겁다.

TCP, UDP는 transport layer, IP는 internet layer에 존재

Application Layer

  • 어플리케이션 레벨에서 구현, 관리
  • 네트워크 기능을 사용하는데 목적

System Layer

  • 하드웨어, 펌웨어, OS레벨에서 구현 관리
  • 네트워크 기능을 지원하는데 목적

socket, port는 Application Layer와 System Layer중간에 위치한 존재

port

  • application의 process와 연결되는 데이터 채널

socket

  • 인터넷 상에 존재하는 port 번호 + ip address를 식별하기 위한것. 일종의 주소

  • 한쌍의 소켓(client-server)로 하나의 connection이 생성

  • 소켓 통신(TCP)

    • Socket 클래스는 데이터를 보내는쪽에서 객체를 생성하여 사용
    • 데이터를 받는쪽에서 클라이언트 요청을 받으면, 요청에 대한 Socket 객체를 생성하여 데이터를 처리
  • Datagram(UDP)

    • ServerSocket과 달리 DatagramSocket을 통해 보내기, 쓰기가 가능하다.
    • TCP에서는 스트림 객체를 얻어 데이터를 주고 받았지만, UDP통신을 할때는 스트림을 사용하지 않고 DatagramPacket이라는 클래스를 사용한다.
  • 소켓통신 예제

package ch28;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServerSample {
    public static void main(String[] args) {
        SocketServerSample sample = new SocketServerSample();
        sample.startServer();
    }

    private void startServer() {
        ServerSocket server = null;
        Socket client = null;
        try {
            server = new ServerSocket(9999);
            while (true) {
                System.out.println("server-waiting for request");
                client = server.accept();
                System.out.println("server accept");
                InputStream stream = client.getInputStream();
                BufferedReader in = new BufferedReader(new InputStreamReader(stream));
                String data = null;
                StringBuilder receivedData = new StringBuilder();
                while ((data = in.readLine()) != null) {
                    receivedData.append(data);
                }
                System.out.println("received data : " + receivedData);
                in.close();
                stream.close();
                client.close();
                if (receivedData != null && "EXIT".equals(receivedData.toString())) {
                    System.out.println("stop socket server");
                    break;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (server != null) {
                try {
                    server.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

클라이언트 응답

server-waiting for request
server accept
received data : I like java 2023-07-08T22:18:46.772863
server-waiting for request
server accept
received data : I like java 2023-07-08T22:18:47.805696
server-waiting for request
server accept
received data : I like java 2023-07-08T22:18:48.808932
package ch28;

import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.time.LocalDateTime;

public class SocketClientSample {
    public static void main(String[] args) {
        SocketClientSample sample = new SocketClientSample();
        sample.sendSocketSample();
    }

    private void sendSocketSample() {
        for (int i = 0; i < 3; i++) {
            sendData("I like java " + LocalDateTime.now());
        }
    }

    private void sendData(String s) {
        Socket socket = null;
        try {
            System.out.println("client connecting");
            socket = new Socket("127.0.0.1", 9999);
            System.out.println("client connect status : " + socket.isConnected());
            Thread.sleep(1000);
            OutputStream stream = socket.getOutputStream();
            BufferedOutputStream out = new BufferedOutputStream(stream);
            byte[] bytes = s.getBytes();
            out.write(bytes);
            System.out.println("client : send data");
            out.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

서버 응답

client connecting
client connect status : true
client : send data
client connecting
client connect status : true
client : send data
client connecting
client connect status : true
client : send data

Optional

null 처리를 간편하게 하기 위한 T타입의 객체의 래퍼 클래스

  • Null에 대한 위험이 줄어든다. NullPointerException
  • null 체크로 인한 코드양 감소 if(num ≠ null)
public class OptionalTest {
    public static void main(String[] args) {
        Optional<String> emptyString = Optional.empty();//데이터가 없는 optional객체
        
        String common = null;
        Optional<String> nullableString = Optional.ofNullable(common);//null을 가질 수 있는 객체
        
        common = "common";
        Optional<String> commonString = Optional.of(common);//반드시 데이터가 들어갈 수 있는 객체
    }
}
private static void getOptionalData(Optional<String> data) throws Exception {
        String defaultValue = "default";
        String result1 = data.get();
        String result2 = data.orElse(defaultValue);
        Supplier<String> stringSupplier = new Supplier<String>() {
            @Override
            public String get() {
                return "godOfJava";
            }
        };
        String result3 = data.orElseGet(stringSupplier);
        Supplier<Exception> exceptionSupplier = new Supplier<Exception>() {
            @Override
            public Exception get() {
                return new Exception();
            }
        };
        String reuslt4 = data.orElseThrow(exceptionSupplier);
    }
  • Optional객체를 통해 데이터를 꺼내는 방법
    • get()
      • 데이터가 없을 경우 null 리턴
    • orElse()
      • 값이 없을 경우 대체하는값 리턴
    • orElseGet()
      • Supplier 인터페이스를 활용해서 데이터를 꺼냄
    • orElseThrow()
      • 값이 없을 경우 exception 발생

날짜 관련 클래스

java8 이전 날짜 클래스는 쓰레드에 안전하지 않았으며, immutable하지 않았다.

또한 연도가 1900년, 월은 1, 일은 0부터 시작하여 날짜 계산에 불편함을 제공했음

병렬 배열 정렬

배열 정렬 관련 메소드 추가

  • sort()
    • 단일 스레드 사용
  • parallelSort()
    • 여러 스레드 사용하며, 더 많은 CPU자원을 사용
    • 배열의 요소가 5000개 이상부터 sort()보다 성능이 빠르다.

Lambda

  • 익명 클래스 사용 시 가독성이 떨어져서, 이를 보완하기 위해 람다 표현식 탄생
  • lambda는 인터페이스에 메소드가 하나인 것만 적용 가능하다.
    • 이러한 인터페이스를 Funtional Interface라고 하며 구분하기 위해 @FuntionalInterface를 사용한다.
  • 익명 클래스 → 람다 표현식, 람다표현식 → 익명 클래스로 전환 가능
(int x, int y) -> x+y
interface Calculate {
	int operation(int x , int y);
}
private void calculateClassic() {
	Caculate cacular = new Caculate() {
		@Override
		public int operation(int a, int b){
			return a+b;
		}
	};
//Caculate cacular = (a,b) -> a+b;
}

java.util.funtion 패키지

자주 사용 되는 다양한 함수형 인터페이스 제공

Stream

컬렉션(배열포함)의 저장요소를 하나씩 참조해서 람다식으로 처리할 수 있는 반복 연산자

컬렉션에는 stream을 사용할 수 있지만, 아쉽게도 배열에는 스트림을 사용할 수 없다. 하지만 배열을 리스트로 변환하거나 Arrays 클래스의 stream()을 사용하여 변환할 수 있다.

Integer[] values = {1,3,5};
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));

Integer[] values = {1,3,5};
List<Integer> list = Arrays.stream(values).collect(Collectors.toList());
  • stream 장단점

stream은 Iterator랑 비슷한 반복자 이지만 아래와 같은 차이점을 가진다.

  1. 내부 반복자이므로 처리 속도가 빠르고 병렬처리에 효율적이다.
    1. 외부 반복자
      1. for문과 Iterator는 컬렉션 요소를 컬렉션 밖으로 반복적으로 가져와 처리한다.
    2. 내부 반복자를 사용하므로 원본 collection요소의 변경이 일어나지 않는다.
    3. 내부 반복자일 경우 개발자 작성한 데이터 처리 코드를 가지고 컬렉션 내부에서 요소를 반복 처리한다.
    4. 내부 반복자는 멀티코어 CPU를 최대한 활용하기 위해 요소들을 분배시켜 병렬작업한다.
  2. 람다식으로 다양한 요소 처리를 정의할 수 있다.
  3. 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성할 수 있다.

메소드 참조

메소드를 참조해서 매개변수의 정보 및 리턴타입을 알아내 람다식에서 불필요한 매개변수를 제거하는 목적으로 사용

(x,y) -> Math.max(x,y);//Math::max;
  • 유형
    1. static 메소드 참조

    2. 특정 객체의 인스턴스 메소드 참조

    3. 특정 유형의 임의의 객체에 대한 인스턴스 메소드 참조

    4. 생성자 참조

      interface MakeString{
      	String fromBytes(char[] chars);
      }
      private void createInstance() {
      	MakeString makeString = String::new;
      
      }

0개의 댓글