Java Socket读取的数据超出预期

时间:2016-06-20 21:53:47

标签: java sockets web serversocket

我遇到套接字读取的问题,它试图从套接字读取超过20 MB的数据但是应该从套接字读取的数据是4的字节数组。我是Socket的新手编程世界所以我的套接字读取方法确实不是什么问题

以下是我的open套接字连接方法

public void open(String catalogName, String sshHost, String port) {
    String responseCode;
    try {               
        socket = new Socket(sshHost, port); // java.net.Socket
        socket.setSoTimeout(3 * 60 * 1000); // defaulting socket timeout to 3 minutes for now

        input = socket.getInputStream();
        output = socket.getOutputStream();            

        String command = String.format("new|Provider=SQLOLEDB;;;Initial Catalog=%s;", catalogName);
        logger.log(Level.DEBUG, "Executing Command: " + command);
        output.write(getLittleEndianLength(command.length()));
        output.write(command.getBytes());
        output.flush();
        responseCode = getResponse();
        if (!responseCode.equals(ERROR_RESPONSE_CODE)) {
            throw new BaseApplicationException("Invalid response code when connecting to database:" + responseCode);
        }

    } catch (UnknownHostException e) {
        throw new BaseApplicationException(e);
    } catch (IOException e) {
        try {
            socket.close();
        } catch (Exception ee) {}
        throw new BaseApplicationException(e.getMessage());
    }           
}

一旦套接字连接打开,我尝试使用大小为4的字节数组读取缓冲区中的数据,如下所示,从套接字读取的数据不能超过MAX_RX_LENGTH,即20 MB

public String read() {
    // read in the integer that defines the length of the result
    byte[] b = new byte[4];
    int retval = 0;

    try {
        retval = read(b);
        if (retval == -1) return null;

        // convert the integer from Big Endian (used by C#) to little endian (java default)
        ByteBuffer buffer = ByteBuffer.wrap(b);
        buffer.order(ByteOrder.LITTLE_ENDIAN);

        int numberBytes = buffer.getInt();
        if (numberBytes > MAX_RX_LENGTH) // MAX_RX_LENGTH = 20971520 which is 20 MB
            throw new BaseApplicationException("Bytes to read was larger than max allowed. numberBytes="
                    + numberBytes);
        logger.log(Level.DEBUG, "reading " + numberBytes + " bytes");

        if (numberBytes > 0) {

            byte[] bytes = new byte[numberBytes];
            int total = 0;
            int bytesRead = 0;
            // may not be able to read the full message in one try so need to loop
            while (total < numberBytes && (bytesRead = read(bytes, total, numberBytes - total)) >= 0) {
                logger.log(Level.DEBUG, "bytes read:" + bytesRead);
                total += bytesRead;
            }

            return new String(bytes);
        }
    } catch (IOException e) {
        try {
            socket.close();
        } catch (Exception ee) {}
        throw new BaseApplicationException(e.getMessage());
    }
    return null;

}

public int read(byte[] b) throws IOException {
    return input.read(b);
}

public int read(byte[] b, int off, int len) throws IOException {
    return input.read(b, off, len);
}

在我们的生产环境中,我们一直看到像Bytes to read was larger than max allowed. numberBytes=543584032这样的异常消息,即使套接字读取方法只能读取大小为4的字节数组。我们在pre-prod环境中看不到这个问题。有人可以帮助我如何确保从套接字读取的数据少于20 MB?

1 个答案:

答案 0 :(得分:0)

你已经解释了字符串&#34; &#34;作为一个数字,当然,得到废话。该错误在代码中未显示,导致发件人和收件人之间的同步丢失。当发件人发送字符串的某些部分时,收件人期望块的大小,因此变得垃圾。