Tiger developer
Tiger developer

Reputation: 244

Socket java can't receive too much data

This is my socket implementation:

s = new Socket(this.host,this.port);
s.setReceiveBufferSize(2048*2048);
s.setSendBufferSize(2048*2048);

And when I receive too much data my data is cropped like this:

Recieving Message: {"cmd":"209","args":{"type":1,"messages":[{...},{...},{...},{..{...},{�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������...

[EDIT] I create a class called InputReader that implements a Runnable, this class inside has a run method and a while condition:

private class InputReader implements Runnable {
    private DarkStarSocketClient main;
    private InputStream in;
    private boolean disconnected = false;

    public InputReader(DarkStarSocketClient main, InputStream in) {
        this.main = main;
        this.in = in;
    }

    public void run() {
        while (!disconnected) {
            try {

                byte hi = (byte) in.read();
                if (hi == -1) {
                    main.disconnect();
                    MessageBuffer dummy = new MessageBuffer(new byte[0]);
                    postRequest(dummy);
                    break;
                }
                byte lo = (byte) in.read();
                int len = ((hi & 255) << 8) + (lo & 255) << 0;

                byte[] msgBytes = new byte[len];

                in.read(msgBytes);
                MessageBuffer buf = new MessageBuffer(msgBytes);
                handleApplicationMessage(buf);

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

This is the implementation of the function handleApplicationMessage:

private void handleApplicationMessage(MessageBuffer msg) throws Exception {
    byte command = msg.getByte();

    switch (command) {
        case SimpleSgsProtocol.LOGIN_SUCCESS:
            reconnectKey = msg.getBytes(msg.limit() - msg.position());
            loggedIn = true;
            responseHandler.loggedIn();
            break;
        case SimpleSgsProtocol.LOGIN_FAILURE: {
            String reason = msg.getString();
            responseHandler.loginFailed(reason);
            break;
        }
        case SimpleSgsProtocol.LOGIN_REDIRECT: {
            String host = msg.getString();
            int port = msg.getInt();
           break;
        }
        case SimpleSgsProtocol.SESSION_MESSAGE: {
            checkLoggedIn();
            byte[] msgBytes = msg.getBytes(msg.limit() - msg.position());
            responseHandler.receivedSessionMessage(msgBytes);
            break;
        }
        case SimpleSgsProtocol.RECONNECT_SUCCESS:
            loggedIn = true;
            reconnectKey = msg.getBytes(msg.limit() - msg.position());
            responseHandler.reconnected();
            break;
        case SimpleSgsProtocol.RECONNECT_FAILURE:
            String reason = msg.getString();
            this.disconnect();
            break;
        case SimpleSgsProtocol.LOGOUT_SUCCESS:
            loggedIn = false;
            break;
        default:
            throw new IOException("Unknown session opcode: " + command);
    }
}

Upvotes: 2

Views: 193

Answers (1)

Peter Lawrey
Peter Lawrey

Reputation: 533442

Most likely you have a bug in your code.

The most common mistake is to ignore the length of data actually read when you call read. e.g.

for(int length; (length = in.read(buffer)) > 0; ) {
    // you must use the actual length and not assume the buffer is always full.

If you ignore the length, you assume the whole buffer has useful data when only the start is right.


EDIT: As I guessed you are ignoring the length actually read. The minimum is 1 no matter how big a byte[] you give it.

in.read(msgBytes);

should be

int length = in.read(msgBytes);
// keep reading until you have everything.

Your life would be a lot simpler if you used DataOutputStream and DataInputStream

 private final DataInputStream in;

 try {
    while (!disconnected) {
        int length = in.readShort() & 0xFFFF;
        byte[] msgBytes = new byte[length];
        in.readFully(msgBytes); // keeps reading until the whole buffer is read.
        try {
            MessageBuffer buf = new MessageBuffer(msgBytes);
            handleApplicationMessage(buf);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
 } catch (EOFException expected) {

 } catch (Throwable t) {
    System.err.println("Fatal error");
    t.printStackTrace();
 }

Upvotes: 5

Related Questions