服务器如何知道收到的消息何时实际结束?

时间:2012-05-29 21:19:28

标签: java sockets client-server inputstream eofexception

我正在尝试实现一个服务器,当它收到一条消息时它会做这样的事情:

try{
       ObjectInputStream is = new ObjectInputStream(clientSocket.getInputStream());
       String message = (String)is.readObject();
       ActivateCommand(message,clientSocket);
       is.close();
    }

和ActivateCommand:

private void ActivateEwolfCommand(String msg, Socket clientSocket) throws IOException 
{
    ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
    Gson gsonObject = new Gson();
    .
    //code which makes a Json string
    .
    os.writeObject(json);
os.close();
}

现在,当我通过junit测试向本地主机发送消息进行测试时,它工作正常。但是当尝试从C#客户端连接到服务器时,客户端连接但服务器在到达clientSocket.getInputStream()时抛出EOF异常。 我猜它发生是因为服务器不知道消息什么时候结束但我不知道那是不是真的如此,如果是,那我该如何解决呢?

3 个答案:

答案 0 :(得分:0)

InputStreamread()上没有更多可用数据时 - 这基本上是导致EOF的原因。可用的数据量由客户端决定 - 它写入Socket的OutputStream侧的数据在服务器端的Socket InputStream上显示。您可以调用InputStream.available()来估算仍然可以read()的字节数。

但是你的代码试图使用ObjectInputStream读取一个Object - 这个类有自己的协议来读取一个序列化的字节流并将其转换为一个对象 - 如果找不到完成任务的字节,这会抛出EOF例外。如果您的客户端使用C# - 那么为序列化对象写入的字节格式肯定不会与服务器端ObjectInputStream的预期相同。

答案 1 :(得分:0)

这就是为什么用套接字和对象流创建自己的客户端 - 服务器协议是个坏主意。很多人花了很多年时间带你,哦,好吧:

  • SOAP
  • REST
  • RMI
  • Hessian矩阵
  • CORBA
  • 节俭

以及众多其他协议。当然其中一个,如果不是5或6,就足以解决你的问题,包括所有框架问题。

答案 2 :(得分:0)

如果要通过套接字发送字符串,则ObjectInputStreamObjectOutputStream不是正确的流实现。这些流实现使用Java对象序列化。即使您序列化String个实例,结果字节也不会与使用适当字符编码的纯字符串到字节转换相同。

C#应用程序完全不了解Java序列化。

考虑使用PrintWriter为您的信息流写字符串,并使用BufferedReader进行阅读。

PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));
writer.println(...);


BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
String line = reader.readLine();

然后你可以逐行读写字符串。 这只是一个起点。如果你想实现自己的协议,你必须注意更多的点。例如,您可以阅读某些TCP协议的规范,例如POP3FTPHTTP 1.0