草庐IT

java - windows下socket读取超时: strange hardcode in native method

coder 2023-11-10 原文

我试图了解如何在 native 代码中处理套接字读取超时,并在那里发现了一些奇怪的硬编码值 5000 毫秒:

if (timeout) {
    if (timeout <= 5000 || !isRcvTimeoutSupported) {
        int ret = NET_Timeout (fd, timeout);
        .....
        .....
    }
}

来源:http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/SocketInputStream.c

如我所见,变量 isRcvTimeoutSupported 通常设置为 true,但在设置套接字选项时可以将其设置为 false:

    /*
     * SO_RCVTIMEO is only supported on Microsoft's implementation
     * of Windows Sockets so if WSAENOPROTOOPT returned then
     * reset flag and timeout will be implemented using
     * select() -- see SocketInputStream.socketRead.
     */

    if (isRcvTimeoutSupported) {
        jclass iCls = (*env)->FindClass(env, "java/lang/Integer");
        jfieldID i_valueID;
        jint timeout;

        CHECK_NULL(iCls);
        i_valueID = (*env)->GetFieldID(env, iCls, "value", "I");
        CHECK_NULL(i_valueID);
        timeout = (*env)->GetIntField(env, value, i_valueID);

        /*
         * Disable SO_RCVTIMEO if timeout is <= 5 second.
         */

        if (timeout <= 5000) {
            timeout = 0;
        }


        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
            sizeof(timeout)) < 0) {

            if (WSAGetLastError() == WSAENOPROTOOPT) {
                isRcvTimeoutSupported = JNI_FALSE;
            } else {
                NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
            }

        }
        ......
        ......
    }

来源:http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/TwoStacksPlainSocketImpl.c

虽然我不太确定,但看起来读取超时应该在大于 5 秒时通过套接字选项设置,如果小于或等于 5 秒则通过 NET_Timeout 设置。是否正确?

不管怎样,这些硬编码的 5 秒是从哪里来的?
我在 MSDN 上没有看到任何解释。

最佳答案

此代码决定如何实现阻塞套接字超时——是使用 SO_RCVTIMEO 还是使用 select,因为 Windows 套接字都支持 (SO_RCVTIMEO 并非在所有平台上都受支持,并且如代码注释中所述,甚至并非所有 Windows 实现都支持它)。 NET_Timeout 在幕后使用 select

基本上算法是:

if SO_RCVTIMEO is supported and timeout is more than 5 seconds:
    use SO_RCVTIMEO
else:
    use select

至于 5 秒阈值的来源,我最好的猜测是他们以某种方式发现(通过测试或反复试验?)select 对于超时值更可靠或更准确超过 5 秒。并不是说它与这个问题特别相关(它针对不同的操作系统),而是 here is an example有人报告 SO_RCVTIMEO 对于较小的超时值不可靠。

关于java - windows下socket读取超时: strange hardcode in native method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49154522/

有关java - windows下socket读取超时: strange hardcode in native method的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  7. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  8. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐