위리윗
722
2017-10-23 09:44:24 작성 2017-10-23 10:09:11 수정됨
14
2009

java서버에 post 전송후 출력 하는 방법이 궁금합니다 ㅠ.ㅠ


자바로 만든 서버가 있고 post형식으로 요청전문을 보낼경우

이때 전송된 body를 출력하는 것을 구현하려는데 뒤에 body가 붙어서 오는것인지 아닌 것인지 조차 모르겠습니다. ㅠㅠ



try {
			in = clientSocket.getInputStream(); // 클라이언트로 부터 바이트 단위로 입력을 받는 InputStream을 얻어와 개통합니다.
			reader = new BufferedReader(new InputStreamReader(in)); // 클라에서 넘어온 형식을 저장

			String eachLine = reader.readLine();
			request.put("method", URLDecoder.decode(eachLine.substring(0, eachLine.indexOf(" /")), "UTF-8"));
			request.put("requestUrl", eachLine.substring(eachLine.indexOf("/"), eachLine.lastIndexOf("HTTP/")));
			request.put("httpVersion", eachLine.substring(eachLine.lastIndexOf("/") + 1, eachLine.length()));
			

			while (eachLine != null && !eachLine.equals("")) // HttpHeader 다읽고 탈출
			{
				System.out.println(eachLine);
				eachLine = reader.readLine();
				if (!eachLine.equals("")) {	// 읽어들이고 나서 해야함 안그러면 빈공간을 읽고 편집할라니까 오류가 발생함
					String name = eachLine.substring(0, eachLine.indexOf(":"));
					String data = eachLine.substring(eachLine.indexOf(":"), eachLine.length());

					request.put(name, data);
				}
			}
			System.out.println("request.get(\"method\") = "+request.get("method"));
			
			if(request.get("method").equals("POST"))	// POST라면
			{
				try {
					System.out.println("reader.readLine(); ========"+reader.readLine());
				eachLine = reader.readLine();	// 바로 전에서 eachLine이 null이거나 eachLine이 ""으로 루프를 빠져나왔으니 
												// 한번 더읽어 주어 내용이 더 있나 검사
				}catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					//System.out.println("●●●●RequestHandler의 IOException = "+e);
				}
				while (eachLine != null && !eachLine.equals("")) // HttpHeader 뒤에 오는게 body니까 끝까지 읽어서 출력
				{
					System.out.println(eachLine);
					eachLine = reader.readLine();
				}
			}
		}

post일 경우 앞서 헤더 부분을 출력할때 null이나 ""일 경우 루프를 빠져나왔으니 한번 더 읽고 그다음에 body를 읽어야한다고 생각하여 위와 같이 짜보았습니다.



<HTML>
	<HEAD>
		<TITLE>POST방식</TITLE>
	</HEAD>
	<BODY>
		<form action="/servlet/PostServlet" method="post">
		<div>
			<label for="name">Name:</label>
			<input type="text" id="name" />
		</div>
		<div>
			<label for="msg">Message:</label>
			<textarea id="msg"></textarea>
		</div>
		
		<div class="button">
			<button type="submit">Send your message</button>
		</div>
		</form>
	</BODY>
</HTML>

클라에서 실행하는 html 은 위 코드처럼 간략하게 버튼을 누르면 name과 msg가 전송 되는 것을 목적으로 하였습니다. 이때 실행되는 PostServlet에서는 따로 동작하는것이 아무것도 없습니다.


실행을하면 get방식은 잘 출력하지만 post방식은 method도 post로 잘 들어오는데 뒤에 body를 출력하기전 readLine에서 동장이 멈추게됩니다.

이미 다 읽어들여서 읽어 들일게 없으니까 동작이 멈춘거같기는 한데... 그럼 method는 잘들어왔는데 body가 안들어왔단 것이니... 왜 안들어왔는지... ㅠㅠ

조언 좀 던져주시면 감사하겠습니다 ㅠ.ㅠ

0
  • 답변 14

  • 구구구구우
    1k
    2017-10-23 10:52:12

    처음 while문에서 body까지 전부 읽어버리는건 아닌지 한번 확인해보셨나요?


    근데 학생이세요??? 제가 보기에 엄청 열심히 하시네요. 아주 좋은 자세로 보입니다.

    그리고 하시려는거 관련해서 톰캣 최종분석이라는 책을 보는걸 추천합니다.






  • 위리윗
    722
    2017-10-23 10:58:41

     구구구구우 학생신분으로 인턴생활을 하고있으며 고성능 서버 개발에 대한 이해를 높이기 위해 사수되는 선배에게 과제형식으로 받아서 공부하고있습니다! 그렇게 봐주신다니 엄청 부끄럽고 감사하네요!



    위 사진과같이 첫번째 while문은 header만을 출력하고 있습니다 ㅠ.ㅠ

  • 구구구구우
    1k
    2017-10-23 11:07:16
    eachLine.equals("")

    일단 제 생각에 body가 넘오 오는지 부터 확인 해야 할거 같은데, 위와 같은 제약조건을 달지 않고 그냥 전부 읽히는대로 전부 출력 해보세요

    그래도 body 부분이 출력이 안된다면, 와이어 샤크같은 패킷 분석기 하나 설치해서 확인 해봐야 할거 같은데.... 만약 body가 진짜로 안넘어 온다면 요청을 보내는 HTML에서 입력을 안채운건 아닌건지 확인이 필요할거 같은데요.

  • 위리윗
    722
    2017-10-23 11:16:43

     구구구구우

    말씀해주신대로 해당 조건문을 없애고 !=null 처리만 해서도 해봤는데 계속 모래시계만 돌더라구요.

    그래서 제 생각은

    1. body가 안넘어왔다면 readLine이 읽을 데이터가 없으니 그대로 다음문장을 실행하여야는것 아닌가?

    2. 하지만 그러지 않고 모래시계만 계속 돌고있으니 읽을 것은 있지만 읽지 못하는 것인가?

    입니다. HTML에서는 제가 값을 입력해서 채우는거라 말씀해주신것처럼 이게 제대로 동작하지 않을 수 있으니 body안에 그냥 텍스트 문자도 넣어봤느넫 이러더군요,

    말씀해주신 패킷 분석기는 제가 지식이 없어 한번 찾아보고 공부해봐야겠네요. 바쁘신 시간 내서 조언 주셔서 정말 감사합니다!

  • 구구구구우
    1k
    2017-10-23 11:31:23

    그래서 바디는 출력이 되었나요. 안되었나요??? 이게 중요하지 모래시계가 뜬게 중요한게 아니죠.


    1. body가 넘어 오건 안오건 readLine메소드는 읽은 데이터가 넘어올때까지 대기하는게 맞습니다. 그래서 보통 소켓 통신시 read를 끝내기 위해서 미리 종료 문자를 정해서 메시지 끝에 붙이죠. 해당 코드에서는 

    eachLine.equals("")

    이거 였고요. 이구문을 지우면 전부다 읽고 또 그다음 데이터가 올때까지( readLine의 경우는 개행이 있는 문자열이 올때까지) 대기 할테구요 


    2. 위의 답변을 토대로 이해하면 됩니다. 데이터가 있는데 읽지 못하는게 아니라 전부다 읽었고 다음 데이터가 올때까지 기다린다는겁니다. 


    3. 패킷 분석기는 본인(로컬)의 네트워크에서 일어나는 패킷 송수신에 대한 모니터링 도구입니다. TCP나 HTTP로 필터링 해서 송수시된 메시지 정보를 제대로 볼수 있어요. 하나 설치 해서 써보세요 공부에 도움이 될거에요

  • 위리윗
    722
    2017-10-23 11:40:30

     구구구구우 아 위에 올린 사진처럼 body는 출력하지 않고 있습니다!

  • 구구구구우
    1k
    2017-10-23 11:45:23

    readLine을 read로 바꿔서 한번 해보시겠어요, 사실 이건 문제가 아닐거 같기 한데, 이것만 딱해보시고 와이어 샤크 깔아서 패킷 보세요 

    그래도 Body가 없으면 HTML에서는 값을 입력을 제대로 안하고 있다는 것 말고 의심하게 있나 싶네요 

  • 위리윗
    722
    2017-10-23 12:52:18

    출력된 header를 자세히 살펴보지 않았네요 ㅠ Content-Lenght 값이 0인걸 보아 body가 넘어오지 않았네요 ㅠ

    read로 바꾸어도 같았습니다!

  • 구구구구우
    1k
    2017-10-23 13:03:06

    그러네요 Content-Lenght 값을 보면 될걸 헛짓걸릴 얘기했었네요......

    HTML 쪽에서 뭘 잘못하고 있다는건데......

  • 구구구구우
    1k
    2017-10-23 13:10:57

    제가 웹을 안해봐서 HTML을 잘 모르거든요("뭐 별거 있겠냐" 라는 생각도 있지만)

    <button type="submit">Send your message</button>

    이태그를 input 태그로 바꾸든지, button태그의 속성중에 form의 id를 지정하는 form속성이 있는거 같은데 이 값을(form id를) 입력해보세요 

  • 구구구구우
    1k
    2017-10-23 13:12:30

    https://www.w3schools.com/tags/tag_form.asp

    https://www.w3schools.com/tags/att_button_form.asp

  • 위리윗
    722
    2017-10-23 13:58:24

     구구구구우 너무 감사합니다!

    버튼의 태그가 문제였네요. 참고하여 수정하니 body도 잘넘어왔으며 readLine으로 읽기에는

    header와 body의 구분점인 "" 때문에 read를 사용하여 출력하였습니다.

    다만 read 메소드가 끝을 만나면 -1을 반환하기에 while ((bytesRead = bufferReader.read(charBuffer))>0)을

    사용하였는데 이 루프를 탈출하지 않고있는 문제가 발생하네요. 본 문제는 좀더 살펴보고 수정해보도록 하겠습니다. 조언해주셔서 정말 감사합니다!

  • 구구구구우
    1k
    2017-10-23 14:15:20

    위에서 얘기 했듯이 read 메소드가 읽을 데이터가 더 올때까지 기다리는 메소드 이고 끝내기 위한 종료 문자가 필요한데 File 입출력에서는 그게 EoF 이겠죠. 파일에 끝에는 저게 무조건 있어서 자바의 Stream에 read메소드가 종료가 알아서 되지만 TCP 통신에서 소켓 Stream은 그렇지 않죠. 종료 문자를 지정해야 합니다.

    그래서 우리는 HTTP프로토콜을 봐야겠죠 HTTP프로토콜에서 Header의 끝은 개행입니다. 바디의 끝은 Header의 Content-Length 를 참고하면 되겠죠

    위에서도 언급했겠지만 톰캣 최종분석이라는 책을 읽으시길 권합니다.

  • 위리윗
    722
    2017-10-23 14:32:27

    구구구구우 이미 말씀해주셨는데 제가 집중하지 않아서 계속 반복되는 답변을 다시게 만들었네요. 죄송하고 감사합니다!

  • 로그인을 하시면 답변을 등록할 수 있습니다.