HelloWorld 만 출력하는 페이지에서 index.html파일을 읽어와서 화면에 출력하도록 수정
RequestHandler 수정전.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}",
connection.getInetAddress(), connection.getPort());
try (InputStream in = connection.getInputStream();
OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
RequestHandler 수정후.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}",
connection.getInetAddress(),connection.getPort());
try (InputStream in = connection.getInputStream();
OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
//1.사용자가 입력한 URL를 'UTF-8' 방식으로 받는다
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
String line = br.readLine();
//log.debug("request line : {}",line);
//2. 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if(line == null)return;
//3.들어온 라인을 공백기준으로 파싱해준다
String [] tokens = line.split(" ");
//4.URL로 부터 들어온 토큰들 확인
while(!"".equals(line)) {
line = br.readLine();
log.debug(tokens[i]);
}
DataOutputStream dos = new DataOutputStream(out);
//5. file을 읽을 수 있게 Byte로 webapp + /index.html를 읽게 한다
byte[] body = Files.readAllBytes(new File("./webapp"+tokens[1]).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
우리가 사용할 것은 token[1]에 있는 /index.html
- http://localhost:8080/user/create?userId=admin&password=1234&name=%EC%A0%95%EC%9B%90%EA%B7%A0&email=wjddnjsrbs97%40naver.com
와 같은 형식으로 회원가입 요청이 GET방식으로 들어온다 (URL)
수정전에는 URL이 들어와도 아무런 매핑을 해주지 않는데 GET 방식으로 들어온 회원가입 URL을 파싱해서 User 객체에 저장해보자
RequestHandler 수정전.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}",
connection.getInetAddress(),connection.getPort());
try (InputStream in = connection.getInputStream();
OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
String line = br.readLine();
if(line == null)return;
//3.들어온 라인을 공백기준으로 파싱해준다
String [] tokens = line.split(" ");
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp"+tokens[1]).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
RequestHandler 수정후.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}",
connection.getInetAddress(),connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out =
connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
// log.debug("request line : {}",line);
// 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if (line == null)
return;
String[] tokens = line.split(" ");
String url = tokens[1];
///1. user/create로 시작하는 URL이 들어올 때 처리해줌
if (url.startsWith("/user/create")) {
//2. create?~~ 에서 ?의 위치를 저장
int index = url.indexOf("?");
//3. ?이후의 url을 핵심 url로 자른다
String pointUrl = url.substring(index+1);
//4. ?이후에 userId=admin&password=1234...로 들어왔을 때
//= 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(pointUrl);
//5. User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),
datas.get("name"),datas.get("email"));
log.debug("user info: {}",user);
}
else {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
요구사항 2번에서 form으로 Get 방식으로 받아서 url parsing을 통해 객체를 생성했다. 이번엔 Post 방식을 이용해서 Http 본문을 parsing 해서 객체를 생성해본다.
RequestHandler 수정전.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}",
connection.getInetAddress(),connection.getPort());
try (InputStream in = connection.getInputStream();
OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
String line = br.readLine();
if(line == null)return;
String [] tokens = line.split(" ");
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp"+tokens[1]).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
RequestHandler 수정후.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
String[] tokens = line.split(" ");
//1. form을 통해 받은 회원가입 정보가 들어있는 http 본문 길이
int contentLength = 0;
System.out.println("출력 시작");
System.out.println("-----------------------------------");
while(!line.equals("")) {
line = br.readLine();
System.out.println(line);
2. 길이에 대한 정보는 Content-Length: 90 이런식으로 나옴
if(line.contains("Content-Length")){
contentLength = getContentLength(line);
}
}
System.out.println("-----------------------------------");
System.out.println("출력 종료");
// 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if (line == null)
return;
String url = tokens[1];
//4. user/create로 들어올 때 처리해줌 (post방식은 url이 달라지지 않음)
if ("/user/create".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),datas.get("name"),
datas.get("email"));
log.debug("user info: {}",user);
}
else {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
//3. http 메세지 parsing, message : information 으로 들어오는 것을 파싱해준다
private int getContentLength(String line) {
String[] headerTokens = line.split(":");
return Integer.parseInt(headerTokens[1].trim());
}
"회원가입"을 완료하면 /index.html 페이지로 이동 현재 /user/create로 유지되는 상태이기 때문에 응답으로 전달할 파일이 없음. 회원가입을 완료한 후 /index.html 페이지로 이동하게 한다.
RequestHandler 수정전.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
String[] tokens = line.split(" ");
int contentLength = 0;
System.out.println("출력 시작");
System.out.println("-----------------------------------");
while(!line.equals("")) {
line = br.readLine();
System.out.println(line);
if(line.contains("Content-Length")){
contentLength = getContentLength(line);
}
}
System.out.println("-----------------------------------");
System.out.println("출력 종료");
if (line == null)
return;
String url = tokens[1];
if ("/user/create".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),datas.get("name"),
datas.get("email"));
log.debug("user info: {}",user);
}
else {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
private int getContentLength(String line) {
String[] headerTokens = line.split(":");
return Integer.parseInt(headerTokens[1].trim());
}
RequestHandler 수정후.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
String[] tokens = line.split(" ");
int contentLength = 0;
while(!line.equals("")) {
line = br.readLine();
if(line.contains("Content-Length")){
contentLength = getContentLength(line);
}
}
// 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if (line == null)
return;
String url = tokens[1];
if ("/user/create".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),datas.get("name"),datas.get("email"));
log.debug("user info: {}",user);
//1. response 헤더를 만들기 위해 output 객체를 만들고 이동할 url로 바꿔준다
DataOutputStream dos = new DataOutputStream(out);
url = "/index.html";
response302Header(dos, url);
}
else {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
//2. 200 Header에서 302 Header로 변경후 요청 url로 redirect 시켜준다
private void response302Header(DataOutputStream dos, String url) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Location: " + url + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
로그인이 성공하면 /index.html로 이동하고, 로그인이 실패하면 /user/login_failed.html로 이동한다 -> 여기서 앞에서 회원가입한 사용자로 로그인 할 수 있어야 하며 로그인이 성공할 경우 요청 헤더의 Cookie 헤더 값이 logined=true, 로그인이 실패하면 Cookie 헤더 값이 logined=false로 전달한다.
RequestHandler 수정전.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
String[] tokens = line.split(" ");
int contentLength = 0;
while(!line.equals("")) {
line = br.readLine();
if(line.contains("Content-Length")){
contentLength = getContentLength(line);
}
}
// 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if (line == null)
return;
String url = tokens[1];
if ("/user/create".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),datas.get("name"),datas.get("email"));
log.debug("user info: {}",user);
DataOutputStream dos = new DataOutputStream(out);
url = "/index.html";
response302Header(dos, url);
}
else {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response302Header(DataOutputStream dos, String url) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Location: " + url + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
RequestHandler 수정후.java
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
String[] tokens = line.split(" ");
int contentLength = 0;
while(!line.equals("")) {
line = br.readLine();
if(line.contains("Content-Length")){
contentLength = getContentLength(line);
}
}
// 만약에 들어온 url이 없으면 리턴해준다 -> 무한루프 막기 위해서
if (line == null)
return;
String url = tokens[1];
if ("/user/create".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//User 객체 생성
User user = new User(datas.get("userId"),datas.get("password"),datas.get("name"),datas.get("email"));
log.debug("user info: {}",user);
//Database에 유저 추가하기
DataBase.addUser(user);
//response 헤더를 만들기 위해 output 객체를 만들고 이동할 url로 바꿔준다
DataOutputStream dos = new DataOutputStream(out);
url = "/index.html";
response302Header(dos, url);
}
//1. login form 요청이 들어올 때
else if ("/user/login".equals(url)) {
String body = IOUtils.readData(br, contentLength);
//userId=admin&password=1234...로 들어왔을 때 = 을 기준으로 key:value parsing
Map<String, String> datas = HttpRequestUtils.parseQueryString(body);
//2. data의 userId값을 받아 DB안에 해당 id를 가진 객체가 있는지 확인
User user = DataBase.findUserById(datas.get("userId"));
//3. 해당하는 id로 회원가입한 이력이 없을 경우 loginFail로 보내준다
if(user == null) {
responseResource(out, "/user/login_failed.html");
return ;
}
//4. id와 password가 모두 일치하는 경우
if(user.getPassword().equals(datas.get("password"))) {
DataOutputStream dos = new DataOutputStream(out);
response302LoginSuccessHeader(dos);
}else {
//5. id는 일치하나 password는 일치하지 않는 경우
responseResource(out, "/user/login_failed.html");
}
DataOutputStream dos = new DataOutputStream(out);
response302LoginSuccessHeader(dos);
}
else {
responseResource(out, url);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
private int getContentLength(String line) {
String[] headerTokens = line.split(":");
return Integer.parseInt(headerTokens[1].trim());
}
//6. Code refactoring
private void responseResource(OutputStream out, String url) throws IOException{
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n");
dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response302Header(DataOutputStream dos, String url) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Location: " + url + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
7. 로그인이 성공했을 때 Cookie를 설정하고 redirect할 경로를 설정
private void response302LoginSuccessHeader(DataOutputStream dos) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Set-Cookie: logined=true \r\n");
dos.writeBytes("Location: " + "../index.html" + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void responseBody(DataOutputStream dos, byte[] body) {
try {
dos.write(body, 0, body.length);
dos.flush();
} catch (IOException e) {
log.error(e.getMessage());
}
}
public class RequestHandler extends Thread {
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);
private Socket connection;
public RequestHandler(Socket connectionSocket) {
this.connection = connectionSocket;
}
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
// url을 가져와서 line으로 받는다
String line = br.readLine();
if (line == null) {
return;
}
//request line : GET /fonts/glyphicons-halflings-regular.woff HTTP/1.1
log.debug("request line : {}", line);
String[] tokens = line.split(" ");
int contentLength = 0;
//기본적으로 로그인을 하지 않으면 false
boolean logined = false;
//Http Header에 있는 정보들을 한줄 한줄 파싱해준다
while (!line.equals("")) {
line = br.readLine();
log.debug("header : {}", line);
//header : Host: localhost:8080로 들어온다면 Host: localhost:8080의 길이를 리턴
//Content-Length: 90 form으로 받으면 Content-Length가 존재
if (line.contains("Content-Length")) {
contentLength = getContentLength(line);
}
//로그인이 되어있다면 header : Cookie: logined=true가 헤더에 포함
if (line.contains("Cookie")) {
logined = isLogin(line);
}
}
String url = getDefaultUrl(tokens);
//form tag에서 회원가입을 하면 user.create로 보낸다
//<form name="question" method="post" action="/user/create">
if ("/user/create".equals(url)) {
//이런식으로 받은 쿼리스트링을 파싱해서 맵으로 바꿔준다
String body = IOUtils.readData(br, contentLength);
Map<String, String> params = HttpRequestUtils.parseQueryString(body);
//User 객체 만들어주기
User user = new User(params.get("userId"), params.get("password"), params.get("name"),
params.get("email"));
log.debug("user : {}", user);
//DB추가
DataBase.addUser(user);
DataOutputStream dos = new DataOutputStream(out);
response302Header(dos);
}
//로그인 요청이 들어왔을 떄 로직처리
else if ("/user/login".equals(url)) {
String body = IOUtils.readData(br, contentLength);
Map<String, String> params = HttpRequestUtils.parseQueryString(body);
User user = DataBase.findUserById(params.get("userId"));
//만약에 해당 id의 유저가 DB에 있고
if (user != null) {
//패스워드 역시 같다면 302 response
if (user.login(params.get("password"))) {
DataOutputStream dos = new DataOutputStream(out);
response302LoginSuccessHeader(dos);
} else {
//패스워드가 다르다면 fail로
responseResource(out, "/user/login_failed.html");
}
} else {
//id가 DB에 없는 경우
responseResource(out, "/user/login_failed.html");
}
}
//가입한 유저 리스트
else if ("/user/list".equals(url)) {
//로그인 상태가 아니면
if (!logined) {
//로그인 하도록
responseResource(out, "/user/login.html");
return;
}
//DB에서 user들을 다 꺼내서 테이블 만들고 출력해준다
Collection<User> users = DataBase.findAll();
StringBuilder sb = new StringBuilder();
sb.append("<table border='1'>");
for (User user : users) {
sb.append("<tr>");
sb.append("<td>" + user.getUserId() + "</td>");
sb.append("<td>" + user.getName() + "</td>");
sb.append("<td>" + user.getEmail() + "</td>");
sb.append("</tr>");
}
sb.append("</table>");
byte[] body = sb.toString().getBytes();
DataOutputStream dos = new DataOutputStream(out);
response200Header(dos, body.length);
responseBody(dos, body);
} else if (url.endsWith(".css")) {
//css적용
responseCssResource(out, url);
} else {
responseResource(out, url);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
//Http Header를 파싱하면서 cookie여부에 따라서 로그인이 되었는지 확인
private boolean isLogin(String line) {
String[] headerTokens = line.split(":");
Map<String, String> cookies = HttpRequestUtils.parseCookies(headerTokens[1].trim());
String value = cookies.get("logined");
if (value == null) {
return false;
}
return Boolean.parseBoolean(value);
}
private void responseResource(OutputStream out, String url) throws IOException {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}
private void responseCssResource(OutputStream out, String url) throws IOException {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200CssHeader(dos, body.length);
responseBody(dos, body);
}
private int getContentLength(String line) {
String[] headerTokens = line.split(":");
return Integer.parseInt(headerTokens[1].trim());
}
private String getDefaultUrl(String[] tokens) {
String url = tokens[1];
if (url.equals("/")) {
url = "/index.html";
}
return url;
}
private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n");
dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response200CssHeader(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
dos.writeBytes("Content-Type: text/css;charset=utf-8\r\n");
dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response302Header(DataOutputStream dos) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Location: /index.html \r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void response302LoginSuccessHeader(DataOutputStream dos) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Set-Cookie: logined=true \r\n");
dos.writeBytes("Location: /index.html \r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
private void responseBody(DataOutputStream dos, byte[] body) {
try {
dos.write(body, 0, body.length);
dos.writeBytes("\r\n");
dos.flush();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}