12

我最近深入研究了使用 java 进行套接字编程,我有一些一般性的问题。

有一个 bind() 方法,以及一个 connect() 和 disconnect()。没有 unbind()。这是因为断开连接时套接字未绑定吗?一旦程序退出,垃圾收集会处理这个问题吗?或者这甚至不是一个有效的问题?

另外,在创建 DatagramSocket 时,如果我只提供端口和地址有什么不同?我正在创建一个程序来从网络上收集数据,因为数据会四处流动并记录下来。我应该只使用本地地址吗?创建套接字时无法使用地址导致我无法收集数据包?

我只是想对这些事情的内部运作有更深入的了解。

4

2 回答 2

16

里面有大约 15 个独立的问题,但我会尽力解决它们:

有一个 bind() 方法,以及一个 connect() 和 disconnect()。没有 unbind()。这是因为断开连接时套接字未绑定吗?

bind()connect()与和分开disconnect()。Bind 用于将套接字绑定到特定端口 - 有效地“侦听”连接,而connect()用于打开与已经在特定端口上侦听的套接字的连接。相当于unbind()close()

一旦程序退出,垃圾收集会处理这个问题吗?或者这甚至不是一个有效的问题?

这是一个完全有效的问题,尽管垃圾收集是一种用于内存管理的技术,而不是套接字/OS 资源管理。如果您不释放特定端口,它将一直与您的应用程序关联,直到您的应用程序终止,然后操作系统将回收它。这是操作系统级别的功能,而不是 JVM 功能等。

另外,在创建 DatagramSocket 时,如果我只提供端口或提供端口和地址有什么不同?

在某些时候,您必须提供您希望连接或绑定的 Internet 地址和端口或套接字。没有办法解决它。

我正在创建一个程序来从网络上收集数据,因为数据会四处流动并记录下来。我应该只使用本地地址吗?创建套接字时无法使用地址导致我无法收集数据包?

我不确定您在这里问什么,您是在谈论记录网络上的所有数据包,也就是嗅探器吗?这将需要的不仅仅是简单的数据报编程。实际上,您必须在网络适配器级别注入自己来拦截数据包,因为它们是离线读取的。你所说的只会让你接收发送到你正在监听的特定端口的数据包。

于 2011-06-15T17:35:57.037 回答
12

ADatagramSocket在断开连接时保持绑定,它是close()解除绑定的方法。请注意,对于 UDP(数据报)套接字,与 TCP(或其他面向连接的)套接字相比,connect()和的语义不同。disconnect()UDP 是一种无连接协议,并且绑定DatagramSocket可以在没有“连接”的情况下发送和接收数据包。该connect()方法具有纯粹的本地效果,因为它使套接字只能向给定的主机/端口发送和接收数据包,即充当过滤器。连接到多播或广播地址的ADatagramSocket将只能发送数据包而不能接收它们。

bind(SocketAddress)用于将套接字附加到本地地址/端口组合,在绑定套接字之前它不能接收或发送任何数据包。构造函数的默认行为是立即绑定套接字。要创建未绑定的“DatagramSocket”,请使用作为参数DatagramSocket(SocketAddress)传递的构造函数。null然后可以在绑定之前将任何自定义配置应用于套接字bind()

据我所知DatagramSocket,超出范围的打开会导致资源泄漏,该对象可能会被垃圾收集,但我很确定底层 UDP 套接字将保持由操作系统分配,直到 JVM 进程退出。

如果在绑定套接字之前未指定地址,则绑定时它将附加到通配符地址(INADDR_ANY),使其能够从任何可用的本地地址接收和发送数据包(除非它稍后“连接”到某个主机)。如果未指定端口(或指定为 0),则套接字将绑定到操作系统选择的某个可用端口(临时端口)。

编辑:一个例子

// bind to INADDR_ANY, allowing packets on all IP addresses of host:
DatagramSocket dsock = new DatagramSocket(55555);
DatagramPacket packet = new DatagramPacket(new byte[8192]);

//next packet can be from anywhere including local host (127.0.0.0/8)
dsock.receive(packet);

// restrict communication to a single host/port:
dsock.connect(new InetSocketAddress("somehost.net", 99));

// next packet can only be from somehost.net on port 99:
dsock.receive(packet);
于 2011-06-15T18:22:40.600 回答