Java.net.SocketException: 在读取大文件时连接重置

4
我们已经构建了基于Java的REST Web服务,用于移动应用与Sharepoint服务器的交互。我们将Web服务托管在Weblogic服务器上。文本数据以JSON格式传输,文件资产以二进制流形式传输到iPad应用程序。我们使用HTTP GET从Sharepoint检索文件资产。我们注意到只有在生产环境中尝试检索大于20MB的文件资产时才会出现问题。
对于大于20MB的文件,我们注意到java.net.SocketException:连接重置或java.net.SocketException:套接字关闭,具体取决于何时关闭套接字。
我们使用Apache HTTPClient 4.2作为HTTP客户端,使用Apache Commons IO库复制输出流。
以下是代码 -
  public org.apache.http.HttpEntity getAssetEntity(final String uri) {


    DefaultHttpClient client = new DefaultHttpClient();
    client.getParams().setParameter("http.connection.stalecheck", new Boolean(true));
    authProvider.addAuthentication(client);

    // Encode only special chars and not the whole URI
    String repURI = "";
    try {
        URL url = new URL(uri);
        URI httpURI = new URI(url.getProtocol(), url.getUserInfo(),
                url.getHost(), url.getPort(), url.getPath(),
                url.getQuery(), url.getRef());
        repURI = httpURI.toString();
    } catch (Exception e) {
        throw new SharePointClientException(e);
    }

    LOGGER.debug("Requesting OutputStream from URL:" + repURI);
    HttpGet httpget = new HttpGet(repURI);
    HttpResponse response = null;
    try {
        response = client.execute(httpget);
        org.apache.http.HttpEntity ent = response.getEntity();
        return ent;
    } catch (IOException e) {
        throw new SharePointClientException(e);
    }

}

protected StreamingOutputDetails getStreamingOutputForChapterAsset(final String assetURL) throws AuthorizationException {
    final HttpEntity assetEntity = getClient().getAssetEntity(assetURL);
    final StreamingOutputDetails streamingOutputDetails = new StreamingOutputDetails();
    streamingOutputDetails.setOutputSize((int) assetEntity
            .getContentLength());
    streamingOutputDetails.setStreamingOutput(new StreamingOutput() {
        @Override
        public void write(OutputStream output) throws IOException {
            try {
                getClient().streamFileAsset(assetEntity, output);
            } catch (SharePointClientException e) {
                // since write() throws IOException, we need to throw a
                // checked exception,
                // so wrap the current exception in an IOException
                throw new IOException(e);
            } catch (SharePointResourceException e) {
                // since write() throws IOException, we need to throw a
                // checked exception,
                // so wrap the current exception in an IOException
                throw new IOException(e);
            } catch (AuthorizationException e) {
                throw new IOException(e);
            }
        }
    });
    return streamingOutputDetails;  
}

   @Override
public void streamFileAsset(org.apache.http.HttpEntity assetEntity,
        OutputStream output) {

    InputStream contentStream = null;
    CloseShieldInputStream closeShieldInputStream = null;
    int bytes = 0;
    try {

        contentStream = assetEntity.getContent();
        closeShieldInputStream = new CloseShieldInputStream(contentStream);
        bytes = IOUtils.copy(closeShieldInputStream, output);
        EntityUtils.consume(assetEntity);

    } catch (IOException e) {
        throw new SharePointClientException(e);
    } finally {

        LOGGER.debug("bytes copied to output stream:" + bytes);
        if(null != closeShieldInputStream) {
            IOUtils.closeQuietly(closeShieldInputStream);
        }
        if (null != contentStream) {
            IOUtils.closeQuietly(contentStream);
        }
    }

}

这种情况只在生产和uat环境中发生,我们无法安装Wireshark来进一步调试。已验证SharePoint设置和Weblogic设置与其他环境相同。

以下是错误的堆栈跟踪 -

Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:204)
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:182)
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:204)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:155)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1792)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1769)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1744)
at com.test.client.SharePointServerListClient.streamFileAsset(SharePointServerListClient.java:217)

谢谢!


连接在重置之前持续多久? - Typo
1个回答

3
对等方关闭了连接,然后您向其写入数据,然后它发出了一个重置信号,然后您尝试读取数据。这是某种应用程序协议错误。可能是因为您发送了一些无效的内容导致对等方关闭了连接。请检查您发送的数据是否正确。

可能是您发送了一些无效的内容导致它关闭:很可能最大请求长度有限制。 - ok2c

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接