0

So I have a client/server game and each time a client makes a move the game outputs to the DataOutputStream and is received by a DataInputStream, the first message is a join message which tells the server the users name (this message is properly received), but all subsequent messages get skewed.

So I initialize the stream like this after connecting to server/client

private DataInputstream out = new DataOutputStream(socket.getOutputStream());

private DataInputStream in = new DataInputStream(socket.getInputStream());

The methods to send the messages to the server:

/**
 * Tells server someone has joined
 */
public void join(ViewProxy proxy, String session) throws IOException {
    out.writeByte('J');
    out.writeUTF(session);
    out.flush();
}

/**
 * tells server that a player took these numbers from a heap
 *
 * @param x the heap
 * @param y the number of items removed
 * @throws IOException
 */

@Override
public void placed(int id, int x, int y) throws IOException {
    out.writeByte('P');
    out.writeInt(id);
    out.writeInt(x);
    out.writeInt(y);
    out.flush();
}

/**
 * Tells server to start a new game
 *
 * @throws IOException
 */
@Override
public void newgame() throws IOException {
    out.writeByte('N');
    out.flush();
}

/**
 * Tells server to quit the game
 *
 * @throws IOException
 */
@Override
public void quit() throws IOException {
    out.writeByte('Q');
    out.flush();
}

Lastly how the server reads the messages:

private class ReaderThread extends Thread {
    public void run() {
        try {
            for (;;) {
                String session;
                byte b = in.readByte();

                switch (b)
                {
                    case 'J':
                        session = in.readUTF();
                        System.out.println("Received J");
                        viewListener.join (ViewProxy.this, session);
                        break;
                    case 'P':
                        System.out.println("Received P");
                        int id = in.readInt();
                        int r = in.readInt();
                        int c = in.readInt();
                        viewListener.placed (id, r, c);
                        break;
                    case 'N':
                        System.out.println("Received N");
                        viewListener.newgame();
                        break;
                    case 'Q':
                        System.out.println("Received Q");
                        viewListener.quit();
                        break;
                    default:
                        System.err.println ("Bad message");
                        break;
                }
            }
        } catch (IOException exc) {
        } finally {
            try {
                socket.close();
            } catch (IOException exc) {
            }
        }
    }
}

When I run the server followed by the client the server receives the initial 'J' (from join method) and everything runs smoothly, but each other subsequent message I get a "Bad Message" as output meaning that the server never received any of the other messages that should have been sent through the stream.

For instance when the placed function is called with some trivial arguments, I get 13 copies of "Bad message" printed to console.

So my question here is what I am I missing? Is the DataOutputStream sending what I want I'm just interpreting it incorrectly or is something more complex going on.

After messing with the program I've removed the flush statements. I also printed what the client was sending and what the server was seeing. The client is sending the right things but the server can't seem to pick up on them. It instead sees 7 zero's (null). 1 for the letter 'P' and 6 for more for what I believe are the three integers.

Also I'm including the a link to my github for access to the full code (located in the src folder) : https://github.com/michaelrinos/Connect-Fout-Client-Server/tree/TCP

Output from the modelproxy class (client side):

Writting J and "john1" <Byte> <UTF>
Sending: 0<Byte>  0<Byte> 5<Byte>

Output from the second modelproxy class (client side):

Writting J and "john2" <Byte> <UTF>

Output from the viewproxy class (server side):

Received J and john1
Received J and john2
0
Bad message
0
Bad message
0
Bad message
5
Bad message

You Can see although the numbers are correct but I lose the leading char.

Mike Rinos
  • 43
  • 1
  • 9
  • I suggest you print the byte you get. It can give you a clue as to what is going wrong. – Peter Lawrey Feb 13 '16 at 01:53
  • Well one of the things I tried was to removing the switch cases and just printing out all the bytes read in and even then I get different outputs what should be sent according to the client is: (74 ('J'), playername in ascii binary, 80 ('P'), 0, 0, 10) The server on the other hand receives (74 ('J'), client1, 74 ('J'), client2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2) – Mike Rinos Feb 13 '16 at 05:46
  • If the client receives `client1` and `client2` you must have sent these as no simple bug would come up with real data like this. – Peter Lawrey Feb 13 '16 at 13:06
  • A Java `char` is 16 bits (not 8). – Elliott Frisch Feb 13 '16 at 20:21
  • @PeterLawrey Yes I do send the client names as part of the join method, the issue occurs after the socket connects and then the first message (which is the Join method which includes the client1/2 names) is sent after that everything goes h**l. – Mike Rinos Feb 14 '16 at 02:51
  • 1
    @ElliottFrisch Yes I can see your point but the point of the DataOutputStream is that it supports the sending of java primitives through the process of first binary encoding them, sending them, and then through DataInputStream decode them. Also in a similar version of the code I wrote using UDP and DataOutputStream the client sends the same message out.writeByte('P') and the server is able to successfully receive the message – Mike Rinos Feb 14 '16 at 02:59
  • Your real code uses `writeByte(),` not `writeInt().` Please clarify. – user207421 Feb 16 '16 at 01:10
  • @EJP Thats the thing though, I have no issue reading in the 'J' and the "player1" the issue is in the next method. Like I said in a previous comment the switch statement and everything in the server side is recycled from an older UDP version of the code, where it handled the messages without issue but now using TCP and sockets the server connects and handles the first 2 clients connecting but then I send the second message 'P' and the server receives all zeros. Even when I hard code writeInt(9) – Mike Rinos Feb 16 '16 at 03:21
  • So where are the length words written by `writeUTF()`? They don't show up in the byte output you posted above. Either it's wrong or the code isn't the real code, or you're writing more to the stream, or reading it somewhere else, so as to get out of sync. – user207421 Feb 16 '16 at 03:26
  • I never write the length of the string. Even on the DataOutputStream documentation the writeUTF function states that it sends the length of the bytes written. So I figured based on that the readUTF method should be able to decode the string properly. Edit: I just removed the writeUTF entirely to see if maybe that was what caused the other issues, but it didn't have any effect – Mike Rinos Feb 16 '16 at 03:37
  • Yes. That's what I said. `writeUTF()` writes the length of the string. I quote: 'written by `writeUTF().`' It doesn't appear in the bytes of output you showed. You need to show what bytes were actually received and what sent them and what received them. At present your question is just a mass of inconsistencies. – user207421 Feb 16 '16 at 04:51
  • Why do I need to write the length of the string? If I'm sending and receiving the proper string I shouldn't have to change that method. – Mike Rinos Feb 16 '16 at 17:56
  • Sigh. *Nobody has said you need to write the length of the string.* **I** have said, three times now, that `writeUTF()` writes it. Four. What I am asking you, over and over again, is why that length does not appear in the byte output you showed, and therefore how we can be confident that you've posted the actual code. You're not reading what is written. – user207421 Feb 16 '16 at 22:10
  • @EJP I have no idea why it doesn't include the leading zero's I figured that maybe readUTF was handling that, but I guess since you bring it up maybe it doesn't. – Mike Rinos Feb 17 '16 at 01:32
  • It does. Of course it does. Says so in the Javadoc. Must do so, otherwise it couldn't read the data. My question is whether the byte output you posted is complete. If you just called `readUTF()`, you haven't printed all the bytes you received. I will only add that the code you posted does not exhibit the problem you mention. *Ergo* the problem is elsewhere. – user207421 Feb 17 '16 at 02:49

1 Answers1

0

This can't be the real code. Otherwise you would have received 'J', 0x00, 0x07, "player1", etc, where 0x0007 is the length prefix placed there by writeUTF(). Make sure everything you read with readUTF() was written with writeUTF(). You may also be writing something else to the stream not shown here.

You need to catch EOFException separately, and break out of the read loop when you catch it; and you need to not ignore IOExceptions.

DataOutputStream.flush() does nothing unless there is a buffered stream underneath, which there isn't in this case.

user207421
  • 305,947
  • 44
  • 307
  • 483