2017-11-17 1 views
0

작은 게임용 클라이언트를 개발 중입니다. 소켓을 사용하여 요청 및 응답을 구문 분석 할 때 PrintWriterBufferedReader 클래스를 사용합니다.BufferedReader가 두 번째 출력을 읽지 않습니다.

문제점은 BufferedReader이 두 번째로 사용 된 경우입니다 (서버의 두 번째 응답).

예 : 여기에 문제가이 문제를 해결하는 가장 좋은 방법은 무엇입니까 수 무엇

public class BotClient { 

private final Socket socket; 
private final PrintWriter writer; 
private final BufferedReader reader; 

public BotClient(final String gameId, final String botName) throws IOException { 
    this.writer = new PrintWriter(socket.getOutputStream(), true); 
    this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
} 

//Code that connects client to server. Works successfully. 

public void sendGameRequest() { 

try { 
    //This first is the FIRST request to server. This works SUCCESSFULLY. 
    writer.println("GET " + "/playerInfo/?gameId=" + gameId + "&playerName=" + botName + " HTTP/1.0\r\n"); 

    reader.lines().forEach(System.out::println); // This will output game response successfully. 

    //Now the problem occurs below here. I could do the same request but won't get an output. 

    writer.println("GET " + "/playerInfo/?gameId=" + gameId + "&playerName=" + botName + " HTTP/1.0\r\n"); 

    reader.lines().forEach(System.out::println); //EMPTY PRINT 

    // The above is EXACTLY the same request however this prints out nothing. 

?

+0

왜 HTTP 클라이언트를 사용하지 않습니까? – sturcotte06

+0

서버가 아무 것도 또는 빈 문자열을 쓸 것입니다. 그것을 확인하십시오. – davidxxx

+0

두 번째'lines()'을 호출하기 전에'close()'를 사용하여 첫 번째 스트림을 닫는 것은 어떨까요? –

답변

0

분석

내가 두 번째 writer.println() 메서드 호출이 일어나지 않을 것을 가정 문 이유는

reader.lines().forEach(System.out::println); 

는, 스트림의 라인을 읽는 설명하면서 스트림의 마지막에 (즉, 소켓이 닫힌 경우)에 도달하지 않습니다. 그것은 제 요청 후에 접속이 원격 배에 의해 폐쇄 된 것일 수

writer.println("GET " + "/playerInfo/?gameId=" + gameId + "&playerName=" + botName + " HTTP/1.0\r\n");

:

0

내가 보는 바와 같이, 이는 HTTP 요청이다. 따라서 요청을 보낼 때마다 연결을 열고 요청을 보내고 기다린 후 응답을 받고 소켓을 닫아야합니다.

이것은 책의 추출기입니다. David Gourley 및 Brian Totty의 Http Definitive Guide. enter image description here

두 번째 요청을 보내기 전에 소켓이 열려 있는지 확인한 다음 그렇지 않은 경우 다시 열어 요청을 보내기 위해 프로세스를 반복하십시오.

+0

같은 소켓을 닫은 후에 열 수 있습니까? 나는 그것이 가능하지 않다고 생각했다. – bob9123

+0

이 답변은 당신을 도울 수 있습니다 : https://stackoverflow.com/questions/9794559/client-reconnect-java-socket 그것은 소켓이 닫히고 그것을 다시 연결하는 다른 방법을 설명합니다. –

+0

내 유스 케이스에 소켓을 닫거나 다시 연결하는 방법을 권장합니까? 아니면 더 효율적인 방법으로 문제를 해결할 수 있습니까? – bob9123

0

reader.lines()은 파일 끝에 도달 할 때까지 reader.readLine()을 반복적으로 호출하는 것과 같은 스트리밍보기를 제공하고 있습니다. 전체 스트림을 읽은 후에는 더 이상 읽을 줄이 없습니다.

줄을 저장해야합니다. 이 작업을 수행하는 가장 쉬운 방법은 목록으로 그들을 수집하는 것입니다 :

List<String> lines = reader.lines().collect(Collectors.toList()); 
lines.forEach(System.out::println); 

InputStreamReader에 대한 경고 : 당신이 어떤 캐릭터 세트를 제공하지 않기 때문에,이 시스템의 디폴트 캐릭터 세트를 사용합니다. 이것은 코드가 다른 운영 체제에서보다 Windows에서 다르게 실행됨을 의미합니다. Windows 머신은 아마도 비 Windows 머신과 통신 할 수 없습니다.

는, 모든 시스템에서 동일하게 실행되도록 명시 적 캐릭터 세트 지정하려면 독자 터미널 스트림 작업을 실행하는 동안 수술을해서는 안

this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); 
0

문서 says

합니다. 그렇지 않으면, 터미널 스트림 작업의 결과가 정의되지 않습니다. 터미널 스트림 작업을 실행 한 후 판독기가 다음 문자 나 행을 읽을 특정 위치에있을 것이라는 보장은 없습니다.

+0

이것이 내 시나리오에 어떻게 적용됩니까? 내 두 번째 요청은 터미널 작업 후에 발생하지만 그 동안은 발생하지 않습니다. – bob9123

+0

첫 번째 반복 후에 입력 스트림을 닫지 않았습니다. 그것을 닫고 새 것을여십시오. – LifeStyle

+0

그래서 모든 요청에 ​​대해 새로운 소켓을 사용해야합니까? – bob9123

관련 문제