Java 的UDP的实现主要靠的是DataGramSocket类来实现,基础的东西网上多的是,例子也是一大片的。这里如果想学最基础的东西建议不要怎么看,本文主要对UDP的连接问题的一个概述:
Java
Connect:这个是jdk api文档的东西
1. public void connect(InetAddress address,
int port)
将套接字连接到此套接字的远程地址。当套接字连接到远程地址时,包就只能从该地址发送或接收。默认情况下不连接数据报套接字。
如果套接字要连接的远程目标不存在或不可到达,并且收到了该地址的目标不可达ICMP 包,那么后续发送和接收的调用可能会抛出 PortUnreachableException。注意,不能保证一定抛出该异常。
在连接时检查调用者对给定主机和端口的发送和接收数据报权限。当连接建立起来后,接收和发送除了对包和套接字的地址和端口进行匹配外,对传入和传出的包将不再执行任何安全性检查。对于发送操作,如果设置了包的地址并且包的地址和套接字的地址不匹配,则将抛出 IllegalArgumentException。连接到多播地址的套接字只能用于发送包。
参数:
address- 套接字的远程地址。
port- 套接字的远程端口。
抛出:
IllegalArgumentException- 如果地址为 null,或端口超出了范围。
SecurityException- 如果不允许调用者向此地址和端口发送也不允许从此地址接收数据报。
另请参见:
disconnect(), send(java.net.DatagramPacket),receive(java.net.DatagramPacket)
2.connect
public void connect(SocketAddress addr)
throws SocketException
将此套接字连接到远程套接字地址(IP 地址+ 端口号)。
参数:
addr- 远程地址。
抛出:
SocketException- 如果连接失败
IllegalArgumentException- 如果 addr 为 null 或者 addr 是不受此套接字支持的 SocketAddress 子类。
从以下版本开始:
1.4
另请参见:
connect(java.net.InetAddress,int)
首先:介绍下这两个方法,其实SocketAddress类就是InetAddress和端口号的封装,
我们所谓的“应用的IP地址”都是由IP地址(InetAddress)和端口号(port)来实现的
在我们应用的时候Java为了给我们封装这个IP地址就于是给我们提供了一个SocketAddress类。
所以归根结底这两个方法还是一样的,只不过就是改了下形式。
我当时的疑惑:当时在看API文档的时候,它里面就有一个Connect方法但是,明明是UDP是面向无连接的,所以由此产生疑惑。
在网上搜了一下,还没有将这个问题的。我去烦死我了,所以在SRC源代码码中
下面看看jdk给出的源代码:
/**
* Sends a datagram packet from thissocket. The
* <code>DatagramPacket</code>includes information indicating the
* data to be sent, its length, the IPaddress of the remote host,
* and the port number on the remote host.
*
* <p>If there is a security manager,and the socket is not currently
* connected to a remote address, thismethod first performs some
* security checks. First, if<code>p.getAddress().isMulticastAddress()</code>
* is true, this method calls the
* security manager's<code>checkMulticast</code> method
* with<code>p.getAddress()</code> as its argument.
* If the evaluation of that expression isfalse,
* this method instead calls the securitymanager's
* <code>checkConnect</code>method with arguments
*<code>p.getAddress().getHostAddress()</code> and
* <code>p.getPort()</code>.Each call to a security manager method
* could result in a SecurityException ifthe operation is not allowed.
*
* @param p the <code>DatagramPacket</code> to be sent.
*
* @exception IOException if an I/O error occurs.
* @exception SecurityException if a security manager exists and its
* <code>checkMulticast</code> or<code>checkConnect</code>
* method doesn't allow the send.
* @exception PortUnreachableException may be thrown if thesocket is connected
* to a currently unreachabledestination. Note, there is no
* guarantee that the exception willbe thrown.
* @exception java.nio.channels.IllegalBlockingModeException
* if this socket has an associatedchannel,
* and the channel is in non-blockingmode.
* @exception IllegalArgumentException if the socket isconnected,
* and connected address and packetaddress differ.
*
* @see java.net.DatagramPacket
* @see SecurityManager#checkMulticast(InetAddress)
* @see SecurityManager#checkConnect
* @revised 1.4
* @spec JSR-51
*/
翻译:从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
如果存在安全管理器,且套接字当前没有连接到远程地址,则此方法首先执行某些安全性检查。首先,如果 p.getAddress().isMulticastAddress() 为true,则此方法以 p.getAddress() 作为参数调用安全管理器的checkMulticast 方法。如果该表达式的值为 false,此方法改为调用安全管理器的以p.getAddress().getHostAddress() 和 p.getPort() 为参数的 checkConnect 方法。如果不允许该操作,则每次调用安全管理器方法都会导致 SecurityException。
参数:
p- 将要发送的 DatagramPacket。
抛出:
IOException- 如果发生 I/O 错误。
SecurityException- 如果安全管理器存在并且其 checkMulticast 或 checkConnect 方法不允许进行发送。
PortUnreachableException- 套接字连接到当前不可达的目标时可能抛出。注意,不能保证一定抛出该异常。
IllegalBlockingModeException- 如果此套接字具有相关联的通道,且通道处于非阻塞模式。
另请参见:
DatagramPacket, SecurityManager.checkMulticast(InetAddress),SecurityManager.checkConnect(java.lang.String,int)
public void send(DatagramPacket p) throws IOException {
InetAddress packetAddress = null;
synchronized (p) {
if (isClosed())
throw newSocketException("Socket is closed");
checkAddress (p.getAddress(), "send");
if (connectState == ST_NOT_CONNECTED) {
// check the address is ok wihtthe security manager on every send.
SecurityManager security =System.getSecurityManager();
// The reason you want tosynchronize on datagram packet
// is because you dont want anapplet to change the address
// while you are trying to sendthe packet for example
// after the security check butbefore the send.
if (security != null) {
if (p.getAddress().isMulticastAddress()) {
security.checkMulticast(p.getAddress());
} else {
security.checkConnect(p.getAddress().getHostAddress(),
p.getPort());
}
}
} else {
// we're connected
packetAddress = p.getAddress();
if (packetAddress == null) {
p.setAddress(connectedAddress);
p.setPort(connectedPort);
} else if((!packetAddress.equals(connectedAddress)) ||
p.getPort() !=connectedPort) {
throw newIllegalArgumentException("connected address " +
"and packet address" +
" differ");
}
}
// Check whether the socket is bound
if (!isBound())
bind(new InetSocketAddress(0));
// call the method to send
getImpl().send(p);
}
}
从 ST_NOT_CONNECTED(标记是否连接的一个int型变量
static final int ST_NOT_CONNECTED = 0)
如果未连接则试用DataGramPacket里面的IP地址进行传输,如果已经连接上了,则用连接到的IP和端口号来传输,(看红色斜体加粗的代码):这样问题就迎刃而解了。
Java这样做到的好处。限制通信的单向性,有时不需要进行多向通信,这样跟方便。相当于通道通信。编程多的应该能体会到,这会很方便我们实现功能,再也不用封装IP在Data里了。