Contents
1. 요구사항 1. 요구사항
- ch02 반이중 통신을 이용하라 (스레드 필요없음)
- 서버 클라이언트 1대1 구조
- HashMap 만들기 (서버)
- 프로토콜은 GET, POST, PUT, DELETE
- 클라이언트는 메시지를 아래와 같이 보낸다
GET: name -> HashMap 에서 name 키 값을 찾아서 그 값을 클라이언트에게 전달
-> 못 찾으면 404 응답
POST: age/20 -> HashMap 에 age 키 값에 20을 저장한 뒤 클라이언트에게 ok 전달
PUT: name/홍길동 -> HashMap에 name 키 값을 찾아서 홍길동으로 변경한다 -> 못 찾으면 404
DELETE:phone -> HashMap에 phone 키 값을 찾아서 삭제한다 -> 못 찾으면 404package ex20.ch05;
import java.io.*;
import java.net.Socket;
public class MyClient05 {
public static void main(String[] args) {
// 반이중 (Half-duplex) 통신 : 클라이언트
// localhost : loopback address (내 주소)
try {
// 소켓 연결
Socket socket = new Socket("127.0.0.1", 20000); // 127.0.0.1 : 실제 loopback 주소
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader resp = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
// 키보드 입력
// System.out.println("키보드 입력 대기중..");
String reqBody = keyIn.readLine();
// 클라이언트 유효성 검사
// 에러 발생 시 에러 메시지 전송 후 반복문 강제 스킵
if (reqBody.startsWith("GET")) {
if (!reqBody.contains(":")) {
sendError();
continue;
} else {
out.write(reqBody);
out.write("\n");
out.flush();
}
} else if (reqBody.startsWith("POST")) {
if (!reqBody.contains(":") && !reqBody.contains("/")) {
sendError();
continue;
} else {
out.write(reqBody);
out.write("\n");
out.flush();
}
} else if (reqBody.startsWith("PUT")) {
if (!reqBody.contains(":") && !reqBody.contains("/")) {
sendError();
continue;
} else {
out.write(reqBody);
out.write("\n");
out.flush();
}
} else if (reqBody.startsWith("DELETE")) {
if (!reqBody.contains(":")) {
sendError();
continue;
} else {
out.write(reqBody);
out.write("\n");
out.flush();
}
} else {
sendError();
continue;
}
// 응답 확인
String respbody = resp.readLine(); // Main Thread 입력 대기 : 자동 Interrupt
System.out.println(respbody);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void sendError() {
System.out.println("GET:, POST:, PUT:, DELETE: 형식으로 입력해주세요.");
}
}package ex20.ch05;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class MyServer05 {
static Map<String, Object> map = new HashMap<>();
static String[] request;
static String protocol;
static String msg;
public static void main(String[] args) {
// 반이중 (Half-duplex) 통신 : 서버
try {
ServerSocket ss = new ServerSocket(20000);
System.out.println("서버 소켓이 대기중입니다. 연결을 시도해주세요.");
// 서버 소켓이 연결을 인지하면 새 소켓 생성 (포트는 무작위)
Socket socket = ss.accept(); // 프로세스 멈춤 (대기 상태)
System.out.println("소켓이 연결되었습니다.");
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 메시지 계속 반복 : Main Thread
while (true) {
String reqbody = "";
String respbody = "";
// 1. parsing
reqbody = br.readLine();
// 1-1. 서버 유효성 검사
// 테스트할 코드가 있으면 따로 파일 만들어서 테스트하기!
reqbody = checkProtocol(reqbody);
if (!(reqbody.equals("404 Not Found"))) {
request = reqbody.split(":");
protocol = request[0];
msg = request[1];
// A2. switch 사용
switch (protocol) {
case "GET":
respbody = doGet(msg);
bw.write(respbody);
bw.write("\n");
bw.flush();
break;
case "POST":
respbody = doPost(msg);
bw.write(respbody);
bw.write("\n");
bw.flush();
break;
case "PUT":
respbody = doPut(msg);
bw.write(respbody);
bw.write("\n");
bw.flush();
break;
case "DELETE":
respbody = doDelete(msg);
bw.write(respbody);
bw.write("\n");
bw.flush();
break;
default:
respbody = doError();
bw.write(respbody);
bw.write("\n");
bw.flush();
}
} else {
bw.write(reqbody);
bw.write("\n");
bw.flush();
}
/// 아래는 직접 풀은 코드입니다.
// 2. analyze protocol
// // 2-1. Protocol : GET
// if (protocol.equals("GET")) {
// respbody = (String) map.get(msg);
// if (respbody != null) {
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// } else {
// respbody = "404 Not Found";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// }
//
// // 2-2. Protocol : Post
// } else if (protocol.equals("POST")) {
// String[] hash = msg.split("/");
// map.put(hash[0], hash[1]);
// if (hash[0] != null && map.get(hash[0]) != null) {
// respbody = "POST OK";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// } else {
// respbody = "404 Not Found";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// }
//
// // 2-3. Protocol : PUT
// } else if (protocol.equals("PUT")) {
// String[] hash = msg.split("/");
// map.replace(hash[0], hash[1]);
// if (hash[0] != null && map.get(hash[0]) != null) {
// respbody = "PUT OK";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// } else {
// respbody = "404 Not Found";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// }
//
// // 2-4. Protocol : DELETE
// } else if (protocol.equals("DELETE")) {
// if (map.remove(msg) != null) {
// respbody = "DELETE OK";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// } else {
// respbody = "404 Not Found";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// }
// } else {
// respbody = "404 Not Found";
// bw.write(respbody);
// bw.write("\n");
// bw.flush();
// }
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// name
private static String doGet(String msg) {
String respbody = (String) map.get(msg);
if (respbody != null) return respbody;
else return doError();
}
// age/20
private static String doPost(String msg) {
String key = msg.split("/")[0];
String value = msg.split("/")[1];
map.put(key, value);
if (map.get(key) != null) return "POST OK";
else return doError();
}
// name/홍길동
private static String doPut(String msg) {
String key = msg.split("/")[0];
String value = msg.split("/")[1];
map.replace(key, value);
if (map.get(key) != null) return "PUT OK";
else return doError();
}
// phone
private static String doDelete(String msg) {
if (map.remove(msg) != null) {
map.remove(msg);
return "DELETE OK";
} else return doError();
}
/// 코드 메서드화
// error
private static String doError() {
return "404 Not Found";
}
// check protocol
private static String checkProtocol(String msg) {
if (msg.contains(":")) return msg;
else return doError();
}
}Share article