[자바 소캣통신] 88. 소켓통신 응용

김건우's avatar
Feb 24, 2025
[자바 소캣통신] 88. 소켓통신 응용

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 키 값을 찾아서 삭제한다 -> 못 찾으면 404
package 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

gunwoo