2017-10-02 6 views
0

간단한 네트워크 클라이언트를 만들고 있습니다. 그것은 텍스트 파일을 읽고 각 줄을 네트워크에 저장합니다. 맨 끝에는 수신 회선을 읽고 CSV 텍스트 회선으로 응답하는 서버가 있습니다.두 번째 소켓 쓰기가 네트워크에 전송되지 않는 것 같습니다.

내가 테스트를 위해 사용하고 나가는 파일은 간단하다 :
6216448319, 리처드 닉슨에서

6216448319, 리처드 닉슨, 로그 "에 기록됩니다."

응답이 있어야 할 로그 아웃 '로그 아웃'이 뒤 따른다.

첫 번째 줄은 완벽하게 처리되지만 두 번째 줄이 소켓에 쓰여진 것처럼 보이지만 서버는 들어오는 메시지를 전혀 보지 못합니다. 나는 문서와 다양한 튜토리얼을 따라 가려고 최선을 다했으나 본 적이없는 것은 같은 행동을 보이는 것으로 보인다. 내가 뭘 놓치고 있니?

각 행을 자체 파일로 보내면 서버가 올바르게 응답합니다. 당신은 스트림의 말을 무시하고

OUT(29): [6216448319,Richard Nixon,Log In] 
Socket is connected for write. 
Waiting for response... 
Socket is connected for read. 
IN(12): ["Logged in."] 
Socket is connected for EOL 
Read 13 from socket. S 
Socket is connected for EOL 
Read 10 from socket. 
Socket is connected for EOL 
Read -1 from socket. 
OUT(30): [6216448319,Richard Nixon,Log Out] 
Socket is connected for write. 
Waiting for response... 
Socket is connected for read. IN(null): [null] 
Socket is connected for EOL 
Read -1 from socket. 

답변

1
  1. :

    protected Integer call() { 
        LOG.info("Starting spooler for file {}, address {}:{}", spoolFile, ipAddress, port); 
        InetAddress server = null; 
        try { 
         server = InetAddress.getByName(ipAddress); 
         LOG.info("IP Address: {}", server.getHostAddress()); 
        } catch (Exception e) { 
         LOG.error("Unknown host: {}", ipAddress, e); 
        } 
        try (Socket socket = new Socket(server, port); 
         BufferedWriter socketWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
         //PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true); 
         BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
         BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(spoolFile))) 
        ) { 
         // Read the spool file line by line and put it out on the wire. 
         String line; 
         while ((line = fileReader.readLine()) != null) { 
          if (isCancelled()) { 
           LOG.error("Spool has been cancelled."); 
           break; 
          } 
          line = line.trim(); 
          LOG.info("OUT({}): [{}]", line.length(), line); 
          //Wait until the channel has successfully written out the line. 
          LOG.info("Socket is {} for write.", socket.isConnected() ? "connected" : "not connected"); 
          socketWriter.write(line); 
          socketWriter.flush(); 
          TalkmanMessage outMessage = new TalkmanMessage(line); 
          outMessageList.add(outMessage); 
          // Wait for the network to respond. 
          // Apparently, readline() blocks until a message is received. 
          LOG.info("Waiting for response..."); 
          LOG.info("Socket is {} for read.", socket.isConnected() ? "connected" : "not connected"); 
          String msg = socketReader.readLine(); 
          LOG.info("IN({}): [{}]", msg == null ? null : msg.length(), msg); 
          TalkmanMessage inMessage = new TalkmanMessage(msg); 
          inMessage.setDelay(
            Duration.between(outMessage.getTime(), inMessage.getTime()).toNanos()); 
          inMessageList.add(inMessage); 
          //The readline() seems to leave a non-printing byte in the socket. Read that out. 
          int leftOver; 
          do { 
           LOG.info("Socket is {} for EOL", socket.isConnected() ? "connected." : "not connected"); 
           leftOver = socketReader.read(); 
           LOG.info("Read {} from socket.", leftOver); 
          } while (leftOver > -1); 
         } 
        } catch (Exception e) { 
         LOG.error("Unable to read from file/write to .", e); 
        } 
        return 1; 
    } 
    

    로깅 명령은 다음과 같은 출력을 생성합니다. read()이 -1을 반환하면 연결이 닫힙니다.

  2. socket.isConnected()을 계속 테스트하는 것은 잘못되었습니다. 그것은 마술처럼 그릇된 것이 아닙니다. 피어 연결 끊기에 대한 테스트는 아닙니다.

  3. 확실히 을 피어에 작성해야합니다. 즉 모든 행을 전송 한 후 newLine()을 호출 하시겠습니까?

  4. 실제로는 바이트을 복사해야하며, 라인 터미네이터 제거/복원, 트리밍 등은하지 말아야합니다. 스트림은 독자 및 작성자가 아닙니다.

  5. 스풀링 중이라면 왜 모든 회선에 대한 응답을 기대합니까? 스풀링의 핵심은 단지 작성한다는 것입니다. 그리고 현시점에서 반환되는 데이터 (아래)는 라인 당 응답이라는 것을 암시합니다.

  6. 이미 제거 된 EOL을 읽는 중일 것 같습니다. newLine()입니다. Javadoc을 보라. 이것은 말이되지 않습니다. 그리고 당신은 또한 스트림의 끝까지, 당신이 보내는 모든 라인에서 읽을 수 있도록 노력하고 있습니다.

  7. 서버가 보낸 당신은 다음과 같다 :

    IN(12): ["Logged in."]<some line terminator, probably but not certainly CR LF because of below> 
    S <CR><LF> 
    

    그것은 다음 연결을 닫았습니다.

애플리케이션 프로토콜을 철저히 검토 할 것을 제안합니다.

+0

마지막 제안이 열쇠였습니다.프로토콜 자체는 없었지만 레거시 제약으로 인해 서버는 각 응답 후에 소켓이 닫히고 각 전송 전에 새 소켓이 만들어지기를 기대했습니다. –

+0

아니요. 서버는 '예상'이 아니라 각 응답 후에 소켓을 닫는 * 것입니다. 이것이 클라이언트에서'read()'가 -1을 리턴 한 이유입니다. – EJP