【问题标题】:Error with reading inputstream of socket in java 1.8在 java 1.8 中读取套接字的输入流时出错
【发布时间】:2018-04-29 14:45:54
【问题描述】:

以下代码在读取输入流时会出错。我使用以下代码:

public void run() {
    try {
        SocketAddress sockaddr = new InetSocketAddress(nServer, nPort);
        nsocket = new Socket();
        nsocket.connect(sockaddr, 10 * 1000);
        if (nsocket.isConnected()) {
            nsocket.setSoTimeout(20 * 1000); 
            nis = nsocket.getInputStream();
            nos = nsocket.getOutputStream();
            if (nProtocol.equals("ntripv1")) {
                String requestmsg = "GET /" + nMountpoint + " HTTP/1.0\r\n";
                requestmsg += "User-Agent: NTRIP LefebureNTRIPClient/20131124\r\n";
                requestmsg += "Accept: */*\r\n" + "Connection: close\r\n";
                if (nUsername.length() > 0) {
                    requestmsg += "Authorization: Basic " + ToBase64(nUsername + ":" + nPassword) +"\r\n";
                }
                requestmsg += "\r\n";
                nos.write(requestmsg.getBytes());
            } else {
            }

            byte[] buffer = new byte[4096];
            int read = nis.read(buffer, 0, 4096);
            while (read != -1) {
                byte[] tempdata = new byte[read];
                System.arraycopy(buffer, 0, tempdata, 0, read);

                try {
                    dataMessenger.send(Message.obtain(null, MSG_NETWORK_GOT_DATA, tempdata));
                } catch (RemoteException e2) {
                }
                read = nis.read(buffer, 0, 4096);
            }
        }
    } catch (SocketTimeoutException ex) {
        try {
            dataMessenger.send(Message.obtain(null, MSG_NETWORK_TIMEOUT));
        } catch (RemoteException e2) {
        }
    } catch (Exception e) {
            LogMessage(e.getLocalizedMessage());
        e.printStackTrace();
    } finally {
        try {
            nis.close();
            nos.close();
            nsocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            dataMessenger.send(Message.obtain(null, MSG_NETWORK_FINISHED));
        } catch (RemoteException e2) {
        }
    }
}

服务器端可以很好地与其他应用程序配合使用。此代码还与服务器建立连接并获取一些日期,但过了一会儿它在 nis.read 上相当。

代码是用 java 1.8 for android studio 编写的。

有没有人想从服务器获取所有信息并读取所有信息以便在应用程序中使用它。

更新 在 while 循环中使用以下行给出了错误:

read = nis.read(buffer, 0, 4096); 

更新 2 给定的错误是:System.err: java.net.SocketException: Connection reset

【问题讨论】:

  • @larsgrefer 阅读该文章无助于解决解决方案。如果您有解决方案,请提供帮助。
  • 为什么要手动建立HTTP连接? Java 有 HttpUrlConnection 或者如果你不喜欢它,有很多库可以为你处理 HTTP 请求。 BTW:您是否知道如果您在 20 秒内没有收到任何数据(因为您设置的 SoTimeout),您将自动断开连接。
  • “发生错误”不是问题描述。 什么错误?
  • 请发布完整的异常堆栈跟踪。

标签: java sockets inputstream connection-reset http-1.0


【解决方案1】:

发送完消息后,始终在输出流上使用 .flush()。如果必须的话,可以把它想象成一个提交,但它实际上只是一个缓冲问题。

其次。服务器很可能正在使用 http keep-alive 并且没有挂断(即使您输入了Connection: close,这也是 HTTP/1.0 的默认设置);然后挂断是客户端的工作。为此,您需要检测内容是否已完成,因此您必须同时支持内容长度响应标头(如果存在)或“分块”传输编码(如果答案大于任意数量,例如几 kB)。 HTTP 是一项不错的运动...!

您也可以尝试 GET 行上的 no http 版本(暗示 HTTP 0.9),我认为它根本不支持 http keep-alive。

如果服务器假定 keep-alive 处于打开状态(请参阅 https://en.wikipedia.org/wiki/HTTP_persistent_connection),那么这将解释该行为。 另见https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection

我建议您安装 Wireshark 并嗅探流量。使用起来比较直观。您将看到是否所有数据都已发送,以及服务器是否真的忘记关闭(TCP FIN)。

【讨论】:

  • 我添加了行'nos.flush();'在'nos.write(requestmsg.getBytes());'之后它只是仍然没有读取/接收到所有需要的信息。
  • 套接字输出流是无缓冲的,不需要刷新。 Connection: close 标头不能被对等方忽略。
  • @EJP:我们以前见过糟糕的服务器。我不会感到惊讶的是,将 1.0 扔到一个会被忽略,因此它会假定为 1.1,因此默认保持活动状态。我们不知道,OP必须尝试其他方法。至于(未)缓冲的套接字流,你真的不应该指望没有缓冲区。此外,任何类型(套接字或磁盘)的无缓冲 i/o 都是犯罪……在绝大多数情况下。
  • @user2023577 犯罪?垃圾。在 Java 中,没有流的 only 缓冲是,错误的,BufferedOutputStream。 Java 非常明智地使缓冲与流的目标正交。我没有说 1.0 或 1.1。
猜你喜欢
  • 2014-08-02
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-16
  • 2011-05-31
  • 1970-01-01
  • 2015-09-13
相关资源
最近更新 更多