0

I'm trying to implement a server and it does something like this when it receives a message:

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

and the 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();
}

now, when i tested it with sending a message to the local host with a junit test it worked. But when tried connecting to the server from a C# client, the client connected but the server throw an EOF exception when getting to the point of clientSocket.getInputStream(). I'm guessing it happens because the server did not know when the message is suppose to end but i don't know if thats really the case and if it is, then how can i fix it?

CodeMonkey
  • 11,196
  • 30
  • 112
  • 203
  • As a programmer you can stream data with some unique information at the end. At receiving point put an if statement checking whether code has hit the ending bits or not! if it does then exit the loop – TeaCupApp May 29 '12 at 21:26
  • but as you can see I'm just making String msg = (String)is.readObject() and i get the message in the string var... how can i tell it to stop when it sees some special character or something? – CodeMonkey May 29 '12 at 21:35
  • If you want to implement a server Netty may be useful: http://netty.io – Peter Bagyinszki May 29 '12 at 21:55

3 Answers3

0

When there is no more data available on the InputStream to read() - that basically is what causes an EOF. How much data is available is determined by the client - the data that it writes to the Socket's OutputStream on its side appears as such on the InputStream of Socket of the server side. You can call InputStream.available() to get an estimate of number of bytes that can be still read().

However your code is trying to read an Object using an ObjectInputStream - this class has its own protocol to read a serialized byte stream and convert that to an object - if it does not find the bytes to complete the task this can throw the EOF exception. If your client is in C# - the format of bytes this writes for a serialized object will definitely not be the same as expected by the ObjectInputStream on the server side.

Bhaskar
  • 7,443
  • 5
  • 39
  • 51
  • so does it mean that InputStream.available() won't work here? – CodeMonkey May 29 '12 at 21:51
  • `InputStream.available()` will work only as much as it tells you how many raw bytes you can read using ObjectInputStream - this works ok , but that is not enough for completely reading an Object from the - because of mismatch of byte format between C# serialization and java deserialization. You need to consider using some higher level framework that can handle data interoperability between C# and java - or use xml serialization of some sort. – Bhaskar May 29 '12 at 22:00
0

This is why it's a bad idea to create your own client-server protocol with a socket and object streams. Many people have spent many years bringing you, oh, well:

  • SOAP
  • REST
  • RMI
  • Hessian
  • CORBA
  • Thrift

and the multitude of other protocols out there. Surely one of them, if not 5 or 6, is good enough to solve your problem, including all issues of framing.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
0

If you want to send strings over a socket, then an ObjectInputStream or ObjectOutputStream isn't the right stream implementation. These stream implementations use Java object serialization. Even if you serialize String instances, the resulting bytes are not the same as plain string to byte conversion with the appropriate character encoding.

And a C# application doesn't understand Java serialization at all.

Consider using a PrintWriter to write strings to your stream and a BufferedReader for reading.

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();

Then you can read and write strings line by line. This is only a starting point. If you want to implement your own protocol you have to pay attention to some more points. As an example you can read the specifications for some TCP protocols like POP3, FTP or HTTP 1.0.

vanje
  • 10,180
  • 2
  • 31
  • 47
  • just to be sure... I've seen some examples for using a BufferedReader when reading a file and it was something like that: try { BufferedReader in = new BufferedReader(new FileReader("infilename")); String str; while ((str = in.readLine()) != null) { process(str); } in.close(); } catch (IOException e) { } I'm assuming that this line reads a full line from the file until the \n char each time? meaning that in the server case i can use the buffered reader without the while loop only if im assunming someone is not passing me a full file? – CodeMonkey Jun 01 '12 at 08:38
  • This depends on your own protocol specification. You can specify that your client should send a one line string to your server and your server responds always with one line. Or you can define that your server can send a whole bunch of lines with an empty line marking the end of the respond. But then you have to escape empty lines as part of your respond. Or you can send one line containing the number of remaining bytes followed by that line. It's totally up to you, if you decide to implement your own protocol. – vanje Jun 01 '12 at 10:14