0

I have a problem in my server/client TCP multiplayer game whenever I try to send too many messages in a short time (usually over 20 messages in the arc of 20 millis). After a while the messages start to arrive corrupted for some reason (like with integers in place of strings that usually get me a NumberFormatException).

I send informations as Strings using a DataOutputStream and read them with a Scanner.

        inputStream = socket.getInputStream();
        outputStream = socket.getOutputStream();
        in = new Scanner(inputStream);
        out = new DataOutputStream (outputStream);

My questions are: should I use something different from the DataOutputStream/Scanner combination? Is there a faster combination? Should I turn the strings into bytes before sending them?

The strings I send are usually composed by both integers and strings, like "m 2 215 123" or "ep 2".

Andrew
  • 358
  • 10
  • 23
  • 1
    Eh.. why not just send JSON? Isn't that simpler than manual parsing and serializing of data? – Benjamin Gruenbaum Jun 21 '14 at 21:12
  • Well..I didn't consider that at all. What if I have to send a 8x18 bidimensional array of Strings using JSON every 18 millis or so. Is parsing a JSON really faster? The updates are so fast because it's a game we're talking about. And the messages are usually enemies moving on the map. – Andrew Jun 21 '14 at 21:20
  • I'm not sure it's really faster, it just sounds less error prone in your case and you won't get weird `NumberFormatExceptions`, serializing your own data should always be your last resort. – Benjamin Gruenbaum Jun 21 '14 at 21:21
  • 1
    Data serialized through `DataOutputStream` is usually intended to be read with a `DataInputStream`, not a `Scanner`. – Jim Garrison Jun 22 '14 at 04:24

2 Answers2

1

the message start to arrive corrupted

No they don't. The messages don't arrive corrupted. You're just getting out of sync, because you're using a poorly defined application protocol. Use DataInputStream and DataOutputStream symmetrically, as suggested by @JimGarrison.

user207421
  • 305,947
  • 44
  • 307
  • 483
1

Expanding on @EJP's answer, the corruption you are experiencing is a result of an application programming error of some kind.

  • If you are using DataOutputStream to write the data, you should use DataInputStream to read it. And make sure that the sequence of write calls exactly matches the sequence of read calls.

  • If you want to read using a Scanner, then you need to format the data as text, and use a Writer to write it. (Make sure that you use the same character encoding scheme at both ends, and avoid doing nasty things like mapping binary data to text via String(byte[]) ... 'cos they tend to break.)

  • If you are either reading or writing the data using multiple threads that read from / write to a single stream, then you need to use some kind of locking to ensure that the messages interleave correctly / cleanly. Streams are typically NOT thread-safe.


As to whether JSON will give you better performance, you probably need to do some experiments to be sure. Among other things, it will depend on the complexity of the data and the way you chose to encode it in the non-JSON case. (But I'd expect DataOutputStream / DataInputStream to be fastest if you chose an appropriate encoding.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216