java - java Socket不能接收太多数据

标签 java sockets networking

这是我的套接字实现:

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

当我收到太多数据时,我的数据会像这样被裁剪:

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

[编辑] 我创建了一个名为InputReader的类,它实现了一个Runnable,这个类里面有一个run方法和一个while条件:

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

这是函数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);
    }
}

最佳答案

很可能您的代码中有错误。

最常见的错误是在调用read时忽略实际读取的数据长度。例如

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

如果忽略长度,则当只有开头正确时,您会认为整个缓冲区都有有用的数据。


编辑:正如我猜测的那样,您忽略了实际阅读的长度。无论你给它多大的 byte[],最小值都是 1。

in.read(msgBytes);

应该是

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

如果您使用 DataOutputStream 和 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();
 }

关于java - java Socket不能接收太多数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36161105/

相关文章:

java - 如何将带有 Object[] 的 ArrayList 转换为 Object[][] 数组?

java - 忽略 Tomcat 中特定 URI 的 cookie

networking - 需要IP地址

python - LAN 上的服务器/客户端应用程序超时错误

node.js - 如何使用 LWP::UserAgent 接受自签名证书

java - 如何使用 GW EPL 命令和 java 在 TSC 打印机上打印图像

java - Java 有析构函数吗?

c - 服务器 - 客户端通信

java - 在输出流中写入 imageicon

Python套接字似乎无法建立连接