→ 모든 네트워크 통신을 정확한 TCP로 하면 될거같은데 왜 UDP를 쓸까?
TCP는 상대방에 대한 응답을 보장하지만, 이에 대한 처리 비용이 크고 데이터가 무겁다.
TCP, UDP는 transport layer, IP는 internet layer에 존재
System Layer
socket, port는 Application Layer와 System Layer중간에 위치한 존재
port
socket
인터넷 상에 존재하는 port 번호 + ip address를 식별하기 위한것. 일종의 주소
한쌍의 소켓(client-server)로 하나의 connection이 생성
소켓 통신(TCP)
Datagram(UDP)
소켓통신 예제
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
null 처리를 간편하게 하기 위한 T타입의 객체의 래퍼 클래스
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);
}
java8 이전 날짜 클래스는 쓰레드에 안전하지 않았으며, immutable하지 않았다.
또한 연도가 1900년, 월은 1, 일은 0부터 시작하여 날짜 계산에 불편함을 제공했음
배열 정렬 관련 메소드 추가
(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;
}
자주 사용 되는 다양한 함수형 인터페이스 제공
컬렉션(배열포함)의 저장요소를 하나씩 참조해서 람다식으로 처리할 수 있는 반복 연산자
컬렉션에는 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은 Iterator랑 비슷한 반복자 이지만 아래와 같은 차이점을 가진다.
메소드를 참조해서 매개변수의 정보 및 리턴타입을 알아내 람다식에서 불필요한 매개변수를 제거하는 목적으로 사용
(x,y) -> Math.max(x,y);//Math::max;
static 메소드 참조
특정 객체의 인스턴스 메소드 참조
특정 유형의 임의의 객체에 대한 인스턴스 메소드 참조
생성자 참조
interface MakeString{
String fromBytes(char[] chars);
}
private void createInstance() {
MakeString makeString = String::new;
}