【问题标题】:Socket InputStream on windows blocks and swaps queriesWindows 上的 Socket InputStream 阻塞和交换查询
【发布时间】:2019-03-29 10:14:48
【问题描述】:

我正在编写一个简单的 ServerSocket 程序,并通过 url 从两个浏览器选项卡连接到它:http://127.0.0.1:8080/Q1 并在 10 秒暂停后http://127.0.0.1:8080/Q2

我的问题是,在带有 java10 的 ubuntu18 机器上,它运行得又快又好。但是在两台 win 机器上(我的 win8.1 使用 java8 和其他 win10 使用 java11)它在第一次查询后挂断并且长达 2 分钟什么都不做,如果我不发送第二次查询,服务器会保持安静。如果我发送第二个查询,我会在浏览器中获得两个查询的结果(按交换顺序,首先是 Q2,然后是 Q1),并且我的服务器报告读取了这两个查询,接下来的两个浏览器会读取 favicon(也交换了 - 在 90% 的情况下,首先是 Q2,然后是 Q1)。

如果我只是在启动 Q1 后等待(而不启动 Q2),首先我会看到 Socket#1 已创建并等待。它等待 2 分钟并关闭。然后在片刻服务器创建#2套接字并在Q1上快速回答,关闭,创建#3套接字获取并回答浏览器发送的Q1-favicon查询。一切都做得非常快和漂亮。我不想让#1 Socket 暂停。我在 ubuntu18 机器上没有。

我做错了什么?还是我的获胜机器有问题?您的 win 机器是否处理第一个查询而不等待第二个查询?

import java.io.PrintWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.stream.Collectors;
import java.io.IOException;

public class localhost {
    public static void main(String[] args) {
        int portNumber = 8080;
        System.out.println("Started...");
        String s="#";
        String ans="#";
        try (
        ServerSocket serverSocket = new ServerSocket(portNumber)){
            String httpResponse;
            int i=0;
            while(true){
                i++;
                System.out.println("Creating new Clien Socket #"+i);
                try( Socket clientSocket = serverSocket.accept()){
                    System.out.println("Accepted... "+clientSocket.toString());
                    try(InputStream in=clientSocket.getInputStream();){
                        {byte[] buffer = new byte[10000];
                        int total = in.read(buffer);
                        if (total>0) {
                            s = new String(java.util.Arrays.copyOfRange(buffer, 0, total));
                            System.out.println(s);

                            httpResponse = "HTTP/1.1 200 OK\r\n\r\nHello, there, "+ s.substring(5,7) +"!";
                            OutputStream out=clientSocket.getOutputStream();
                            out.write(httpResponse.getBytes());
                        } else { System.out.println("Empty..."); }
                        System.out.println("Finished #"+i+" "+clientSocket.toString());
                        System.out.println();}
                    }
                }
            }

        } catch(Exception e){
            System.out.println("Error: "+e);
        }
        System.out.println("I'm done "+s);
    }
}

UPD:对于 Q1 没有 Q2 的情况,如果我做对了,Wireshark 显示两个套接字 - 50410 和 50411,而服务器接受()-ed 只有一个 - 50411。看起来 50410 导致等待,这个空查询和哪里来的?

【问题讨论】:

  • 您是否在 cmd (windows) 中启动了您的应用程序?
  • 我在所有 3 台机器上使用 VS Code(终端中带有 code-runner 扩展)启动它。
  • 我运行你的代码,它可以工作......
  • 谢谢@Wufo 你从哪个浏览器运行查询?我在win机器上使用chrome,但在ubuntu中使用firefox。我刚刚尝试从 chrome-incognito-mode 和 firefox 发送查询。在这两种情况下,一切正常 - 没有空查询。但是 chrome (all ext off) 不起作用 - 它首先发送空查询。
  • 我从 chrome 发送。我做什么: 1. 启动程序 -> 开始... 创建新的客户端套接字#1 2. 通过 chrome 访问“localhost:8080/Q1”。 3. 看起来 chrome 发送了 2 次,因为控制台日志: .... Finished #1.. Creating #2.. Finished #2... Creating #3...

标签: java networking io inputstream serversocket


【解决方案1】:

similar 问题中,我发现了一个有用的link,说这可能是由“预测网络操作以提高页面加载性能”设置引起的。所以我尝试一一关闭预测设置,它起作用了。在 chrome 版本 73.0.3683.86(官方构建)(64 位)中,此行为是由 chrome 设置“使用预测服务更快地加载页面”引起的。

所以只需转到设置 -> 高级 -> 隐私和安全 -> 使用预测服务更快地加载页面并将其关闭。 (或者,如果您的 chrome 版本中没有它,请尝试关闭类似的设置)。

【讨论】:

  • 为什么要关闭它?这里没有问题需要解决。
  • 观察纯 html 协议 + 确保这不是我的代码错误 -> 了解网络(和 java 网络)如何工作。无价。并帮助其他将努力理解这种行为的人。另外,现在我明白了即使没有任何攻击,空包也不是网络的后方情况。
猜你喜欢
  • 2012-08-24
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多