一些java Datagram Socket问题

时间:2011-06-15 17:28:34

标签: java sockets datagram

我最近已经厌倦了使用java进行套接字编程,我有一些常见的问题。

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

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

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

2 个答案:

答案 0 :(得分:16)

那里有大约15个独立的问题,但我会尽力解决这些问题:

  

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

bind()connect()disconnect()分开。 Bind用于将套接字绑定到特定端口 - 有效地“监听”连接,而connect()用于打开已经侦听特定端口的套接字的连接。等同于unbind()的是close()

  

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

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

  

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

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

  

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

我不确定你在这里问的是什么,你是在谈论在网络上记录所有数据包,又叫嗅探器?这将需要的不仅仅是简单的数据报编程。实际上,您必须在网络适配器级别注入自己,以便在数据包被读取时拦截数据包。您所谈论的内容只允许您接收发送到您正在收听的特定端口的数据包。

答案 1 :(得分:12)

断开连接时DatagramSocket仍然绑定,close()方法将取消绑定它。请注意,对于UDP(数据报)套接字,connect()disconnect()的语义与TCP(或其他面向连接)套接字相比是不同的。 UDP是一种无连接协议,绑定DatagramSocket可以发送和接收数据包,而不需要“连接”。 connect()方法具有纯粹的局部效应,因为它使套接字只能发送和接收给定主机/端口的数据包,即充当过滤器。连接到多播或广播地址的DatagramSocket只能发送数据包而不能接收数据包。

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

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

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

编辑:一个例子

// 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);