웹 서버와 관련 포스팅 중, 웹 서버 프로그램을 사용하는 당위성을 설명하기 위해 직접 Java를 사용하여 HTTP 서버를 구현하고자 합니다. 간단하게 GET 요청만 받는 HTTP 서버를 구현합니다.
Server Socket API
ServerSocket의 클래스는 서버 프로그램을 구현하는데 사용됩니다. 일반적인 서버 프로그램의 과정은 Step1 ~ Step 6으로 나눌 수 있습니다.
Step 1. 서버 소켓 생성, 포트 바인딩
Step 2. 클라이언트로부터의 연결을 기다리고(Connect Listen) 요청이 오면 수락
Step 3. 클라이언트 소켓에서 가져온 InputStream(클라이언트 쪽에서는 OuputStream 이 됩니다)을 읽음
Step 4. 응답이 있다면 OutputStream을 통해 클라이언트에 데이터를 보냄
Step 5. 클라이언트와의 연결을 닫음
Step 6. 서버 종료
출처: https://woolbro.tistory.com/29 [개발자 울이 노트:티스토리]
catch
할 수 있는 지 테스트HTTP Request
을 받아들일 때 어떠한 구조로 받아들이는지 출력문
을 통해 확인HTTP Request
의 Type
을 확인하고, 해당 타입을 DTO
로 전환할 수 있도록 클래스 작성DTO
를 활용하여 HTTP Request
를 객체로 전환HTTP Request
객체의 헤더를 확인하여 적절한 handler method
호출handler method
가 반환한 HTTP Response
객체를 클라이언트에게 응답// 이 예제는 소켓을 활용하여 HTTP서버를 만들어 보기 위한 예제입니다.
// 테스트를 위해 HTTP 동작만 확인했기 때문에, 코드를 참조할 경우
// HTTP request or response 코드만 확인하시고,
// 소켓 관련 코드는 추가적인 정보를 찾아 올바른 코드를 활용하시기 바랍니다.
public class WebSocket {
public static void main(String[] args) {
System.out.println("Server has started on 127.0.0.1:8080 \nWaiting for a connection...");
try {
while(true){
ServerSocket socket = new ServerSocket(8080);
Socket client = socket.accept();
System.out.println("Client connected!");
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
Scanner s = new Scanner(in,"UTF-8");
String requestData = null;
if(s.hasNextLine()){
requestData = s.nextLine();
}
HttpRequestDto httpRequestDto = new HttpRequestDto(requestData);
Dispatcher dispatcher = new Dispatcher();
HttpHandler httpHandler = dispatcher.dispatch(httpRequestDto);
HttpResponseDto httpResponseDto = httpHandler.handle();
out.write(httpResponseDto.getResponseData().getBytes());
s.close();
in.close();
out.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class HttpRequestDto {
private String method;
private String requestUrl;
public HttpRequestDto(String httpRequest){
ArrayList<String> requestList = new ArrayList<>(Arrays.asList(httpRequest.split(" ")));
this.method = requestList.get(0);
this.requestUrl = requestList.get(1);
}
public String getMethod() {
return method;
}
public String getRequestUrl() {
return requestUrl;
}
}
public class HttpResponseDto {
private String responseData;
public HttpResponseDto(String responseData){
this.responseData = responseData;
}
public String getResponseData() {
return responseData;
}
}
public interface HttpHandler {
HttpResponseDto handle();
}
public class DefaultHttpHandler implements HttpHandler{
@Override
public HttpResponseDto handle() {
String responseData = "HTTP/1.1 200 OK\r\n" +
"Server: \r\n" +
"Content-type: text/html\r\n\r\n" +
"<HTML>" +
"<HEAD><TITLE>200</TITLE></HEAD>" +
"<BODY>This is \"/\" Response Data!" +
"</BODY></HTML>";
return new HttpResponseDto(responseData);
}
}
public class HelloHttpHandler implements HttpHandler {
@Override
public HttpResponseDto handle() {
String responseData = "HTTP/1.1 200 OK\r\n" +
"Server: \r\n" +
"Content-type: text/html\r\n\r\n" +
"<HTML>" +
"<HEAD><TITLE>200</TITLE></HEAD>" +
"<BODY>This is \"/hello\" Response Data!" +
"<br>hello world!"+
"</BODY></HTML>";
return new HttpResponseDto(responseData);
}
}
public class Dispatcher {
public HttpHandler dispatch(HttpRequestDto requestDto) throws Exception {
String method = requestDto.getMethod();
String requestUrl = requestDto.getRequestUrl();
if(method.equals("GET")){
if(requestUrl.equals("/")){
return new DefaultHttpHandler();
}else if(requestUrl.equals("/hello")){
return new HelloHttpHandler();
}else if(requestUrl.equals("/favicon.ico")){
return new HelloHttpHandler();
}
}else{
throw new Exception("Not supported Method!");
}
return null;
}
}
구현을 정말 깔끔하게 잘하셨네요!! 혹시 출처를 남기고 블로그에 관련 글을 적어도 될까요???