草庐IT

关于so??ckets:Java中的UDP认为UDP有”连接”

codeneng 2023-03-28 原文

UDP in Java thinks that UDP has "connections"

Java 中的 UDP 认为 UDP 有"连接"。这让我感到惊讶,因为我来自 C 背景,我一直使用 UDP 作为一种即发即弃的协议类型。

在 Java 中测试 UDP 时,我注意到如果远程 UDP 端口未在侦听,我会在尝试发送任何内容之前在 Java 中收到错误。

为了能够判断远程 UDP 端口是否正在侦听,Java 做了什么(没有我要求它)?

(下面的代码在套接字的接收线程中运行。发送在不同的线程中完成。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    try {
        socket = new DatagramSocket(udpPort);
        socket.connect(udpAddr, udpPort);
    } catch (SocketException e) {
        Log.d(TAG,"disconnected", e);
    }
    ...
    while (true) {
        // TODO: don't create a new datagram for each iteration
        DatagramPacket packet = new DatagramPacket(new byte[BUF_SIZE], BUF_SIZE);
        try {
            socket.receive(packet); // line 106
        } catch (IOException e) {
            Log.d(TAG,"couldn't recv", e);
        }
        ...

如果远程套接字未在侦听,

会产生以下错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
java.net.PortUnreachableException:
        at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:556)
        at libcore.io.IoBridge.recvfrom(IoBridge.java:516)
        at java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:161)
        at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:169)
        at java.net.DatagramSocket.receive(DatagramSocket.java:253)
        at com.example.mypkg.MyClass.run(MyClass.java:106)
        at java.lang.Thread.run(Thread.java:856)
 Caused by: libcore.io.ErrnoException: recvfrom failed: ECONNREFUSED (Connection refused)
        at libcore.io.Posix.recvfromBytes(Native Method)
        at libcore.io.Posix.recvfrom(Posix.java:131)
        at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
        ...

  • 如果您提供有问题的代码片段,这将极大地有助于更好地理解您的问题。
  • 您可以发布例外的全文吗?
  • 这对我来说是不合理的。 Java 数据报套接字没有连接的概念。我希望您以某种方式误解了证据,但是没有看到您的代码和完整的异常堆栈跟踪,我怀疑我们能否找到问题的根源。
  • @user1697575 我添加了代码和异常。它的 Android,如果这很重要,但我相信我在服务器 Java 中看到了同样的行为。
  • @StephenC 错误是 ECONNREFUSED
  • 你正在接收,对吧?您是否有权监听您正在接收的端口? new DatagramSocket(udpPort); 在本地端口上创建套接字:
  • 此外,If the remote destination to which the socket is connected does not exist, or is otherwise unreachable, and if an ICMP destination unreachable packet has been received for that address, then a subsequent call to send or receive may throw a PortUnreachableException. Note, there is no guarantee that the exception will be thrown. 来自此处的文档:download.java.net/jdk7/archive/b123/docs/api/java/net/


UDP in Java thinks that UDP has"connections".

不,它没有,但是 UDP(不管 Java)确实有连接的套接字。不是一回事。

This surprised me, coming from a C background where I had always used UDP as a fire-and-forget type of protocol.

你也可以在 C 中 connect() 一个 UDP 套接字。查一下。您所描述的与Java无关。

When testing UDP in Java, I noticed that if the remote UDP port is not listening, I get an error in Java before I attempt to send anything.

那是因为你连接了套接字。这样做的副作用之一是传入的 ICMP 消息可以以错误的形式路由回发送套接字。

What does Java do (without me asking it to) in order to be able to tell whether a remote UDP port is listening?

它调用 BSD Sockets connect() 方法。


首先,很明显这不是使用真正的Java实现的。"libcore.io"包不是 Java SE 库的一部分。这些是 Android 堆栈跟踪。 (这不会改变任何东西......但它可以。)

好的,让我们从异常开始。 java.net.PortUnreachableException 的 javadoc 说:

"Signals that an ICMP Port Unreachable message has been received on a connected datagram."

对于 DatagramSocket.connect(...):

"If the remote destination to which the socket is connected does not exist, or is otherwise unreachable, and if an ICMP destination unreachable packet has been received for that address, then a subsequent call to send or receive may throw a PortUnreachableException. Note, there is no guarantee that the exception will be thrown."

这就是我认为发生的事情。在创建 incoming 套接字之前,客户端系统上的某些东西已在该端口上向服务器发送了一个 UDP 数据包,并且服务器已响应 ICMP 端口不可达。然后创建并连接您的套接字,然后调用 receive。这会执行 recvfrom 系统调用,并且网络堆栈会以 ECONREFUSED 错误代码进行响应...Java 将其变成 PortUnreachableException,

这是否意味着 UDP 是面向连接的?

不是真的,IMO。它只是报告它收到一条 ICMP 消息以响应之前发生的事情。

connect 方法和"连接的套接字"/"连接的数据报"用语怎么样?

IMO,这只是一些笨拙的措辞。"连接"实际上只是指数据报套接字已绑定到特定远程地址和端口的事实......这样您就可以在不指定IP和端口1的情况下发送和接收数据报。

这些"连接"非常脆弱,当然不等于使 UDP"面向连接"。

What does Java do (without me asking it to) in order to be able to tell whether a remote UDP port is listening?

它什么也没做。 Java 只是从先前的 ICMP 消息中报告信息。

1 - 实际上,它的意义远不止于此。例如,绑定告诉客户端操作系统缓冲来自该主机/端口的 UDP 数据包,并将 UDP 数据包(和 ICMP 通知)路由到应用程序。它还告诉它不要以无法访问的 ICMP 端口进行响应。

  • UDP 中的 ECONNREFUSED 必须是 Android 主义。发生的 ICMP 错误应该直接映射到 EPORTUNREACH。 Java 与此无关。连接 UDP 套接字不仅仅是绑定。它将本地 UDP 堆栈调节为 (a) 知道要发送到哪里,(b) 过滤掉不是来自目标的传入数据报,以及 (c) 将传入的 ICMP 错误路由回套接字。


UDP 服务器需要监听本地端口。

这是服务器的代码Stubbing。

1
2
3
4
5
6
7
8
9
10
11
12
13
int portNumber = 59123;
DatagramSocket server = new DatagramSocket(portNumber);

// read incoming packets
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while(true)
{
   server.receive(packet);
   byte[] data = packet.getData();
   String text = new String(data, 0, packet.getLength());

   echo(packet.getAddress().getHostAddress() +":" + packet.getPort() +" received: '" + text +"'");
}

  • 抱歉,我的问题对你来说不够清楚。我的问题是:当我要求它进行侦听时,Java/UDP 如何知道远程端口无法访问。如果我要求在 C 中侦听 UDP 端口,它不会代表我发送任何内容,因此它不会无法侦听。

有关关于so??ckets:Java中的UDP认为UDP有”连接”的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  9. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  10. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

随机推荐