2015-07-13 149 views
1

我的程序基本上是:Server客户端通信的Outputstreams失败

  1. 客户端发送一个字符串到服务器,

  2. 根据此字符串,服务器创建一个ArrayList,

  3. ArrayList被发送回客户端。

这到底是怎么失败的是:

客户端后发送一个字符串,服务器接收它,并没有做任何事情。在这个时候,客户端继续工作并获得NullPointer。

客户端:

public static ArrayList<String> sendStringToServer(String report) { 

    Socket socket; 

    ArrayList<String> fieldsList = new ArrayList<String>(); 

    try { 

     socket = new Socket("localhost", 2345); 

     OutputStream os = socket.getOutputStream(); 
     PrintStream ps = new PrintStream(os, true); 

     ps.println(report); 
     ps.flush(); 

     //Here the debugger should stop and wait for server to create a List 

     //at this point there is no answer, code breaks 
     ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream()); 

     Object object = objectInput.readObject(); 
     fieldsList = (ArrayList<String>) object; 

     socket.close(); 

     return fieldsList; 

    } catch (IOException e1) { 

     e1.printStackTrace(); 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 
    return null; 
} 

}

服务器端:

public class Server { 

private ServerSocket serverSocket; 
private Socket clientSocket; 
private String telegram; 
private StringBuilder telegramSB; 

public static void main(String[] args) throws IOException, JRException { 

    new Server(); 
} 
public Server() { 

    try { 
     serverSocket = new ServerSocket(2345); 

     while (true) { 

      clientSocket = serverSocket.accept(); 
      InputStream is = clientSocket.getInputStream(); 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 

      try { 

       //debugger goes to here and then stops 
       telegram = br.readLine(); 

       int counter = 0; 

       boolean startSeq = false; 

       for (char ch : telegram.toCharArray()) { 

        if (counter == 0 && ch == '/') { 

         startSeq = true; 
        } 

        if (startSeq == true) { 

         telegramSB = new StringBuilder(); 
         telegramSB.append(ch); 
        } 

        if (ch == '\n') { 

         if (telegram.length() < 255) { 

          sendListWithFields(); 

         } else { 

          new Launcher(telegram).run(); 
         } 
        } 
        counter++; 
       } 
      } catch (JRException e) { 

       e.printStackTrace(); 

      } catch (IOException e) { 

       e.printStackTrace(); 

      } 
     } 
    } catch (IOException e) { 

     System.out.println(e); 
    } 
} 
+0

你发送行尾(EOF)字符/ s吗? –

+0

@eyp是的,我做但我的程序永远不会到达那里。它读取bufferedReader然后停止。 –

回答

0

在这里,我的猜测是对的BufferedReader等待填满其缓冲区和你的避风港没有发送足够的数据来做到这一点,并返回,所以它等待更多的数据来临呃,永远不会(因为你的客户停止写作,并开始阅读)。您可以通过将更多数据加载到客户端上的OutputStream并将其刷新来暂时测试此理论。

如果上面是这种情况,那么你可能不想使用BufferedReader,但你在这里还有其他问题,这也意味着你可能想避免使用PrintStream和BufferedReader进行通信和序列化。例如,两个不同机器和JVM上的默认字符编码可能不同。当你创建你的PrintStream和InputStreamReader时,你并没有指定一个字符编码,所以它们最终可能不匹配,而且你写的字符串(包括换行符)最终会被远程端完全不同的理解,这也可能是这是阻止它的原因(客户端以一种方式对换行符进行编码,但服务器期望它以完全不同的方式进行编码),但我认为不太可能。

如果你不这样做使用PrintStream的话,我会使用DataOutputStream/DataInputStream所建议改为:

//Client 
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream()); 
DataOutputStream dout = new DataOutputStream(bufout); 
dout.writeUTF(report); 
dout.flush(); 

//Server 
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream()); 
DataInputStream din = new DataInputStream(bufin); 
String report = din.readUTF(); 

你仍然从BufferedIn/OutputStreams得到缓冲,因此这将是高性能,但数据输入/ OutputStreams将管理可变长度对象的终止 - 它们将发送一个字符串前缀的长度来告诉另一方准确读取多少字节,因此您不需要使用特殊字符来终止您所写的字符串,并且这也意味着你的String的内容并不重要。在上面的例子中,即使它在工作,如果你的字符串中有一个换行符,服务器也会读取直到第一个换行符,而不是你发送的字符串的末尾,这会使它们不同步以用于下一次发送/沿着该流接收。

使用write/readUTF还指定了编码(UTF-8),因此不存在任何不匹配。