package network; import java.io.IOException; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPEchoClientTimeout { private static final int TIMEOUT = 3000; private static final int MAXTRIES = 5; public static void main(String[] args) throws IOException { InetAddress serverAddress = InetAddress.getByName("10.10.25.256"); byte[] bytesToSend = "test data".getBytes(); int servPort = 2004; DatagramSocket socket = new DatagramSocket(); socket.setSoTimeout(TIMEOUT); DatagramPacket sendPacket = new DatagramPacket(bytesToSend, bytesToSend.length, serverAddress, servPort); DatagramPacket receivePacket = new DatagramPacket( new byte[bytesToSend.length], bytesToSend.length); int tries = 0; boolean receivedResponse = false; do { socket.send(sendPacket); try { socket.receive(receivePacket); if (!receivePacket.getAddress().equals(serverAddress)) { throw new IOException( "Received packet from an unknown source"); } receivedResponse = true; } catch (InterruptedIOException e) { tries += 1; } } while ((!receivedResponse) && (tries < MAXTRIES)); if (receivedResponse) { System.out.println("Received: " + new String(receivePacket.getData())); } else { System.out.println("No response -- giving up."); } socket.close(); } }
与 Socket 类不同,DatagramSocket 实例在创建时并不需要指定目的地址,UDP 套接字在进行通信前则不需要建立连接,每个数据报文都可以发送到或接收于不同的目的地址。
DatagramSocket自动选择本地地址和可用端口号,也可以通过setLocalAddress()和 setLocalPort()方法或构造函数,来显式地设置本地地址和端口。
数据报文套接字的超时时间,用来控制调用 receive()方法的最长阻塞时间(毫秒)。
receive()方法将阻塞等待,直到收到一个数据报文或等待超时。
DatagramSocket: 创建
DatagramSocket()
DatagramSocket(int localPort)
DatagramSocket(int localPort, InetAddress localAddr)
以上构造函数将创建一个 UDP 套接字。可以分别或同时设置本地端口和地址。如果没有指定本地端口,或将其设置为 0,该套接字将与任何可用的本地端口绑定。如果没有指定本地地址, 数据包(packet)可以接收发送向任何本地地址的数据报文。
DatagramSocket: 连接与关闭
void connect(InetAddress remoteAddr, int remotePort)
void connect(SocketAddress remoteSockAddr)
void disconnect()
void close()
connect()方法用来设置套接字的远程地址和端口。一旦连接成功,该套接字就只能与指定的地址和端口进行通信,任何向其他地址和端口发送数据报文的尝试都将抛出一个异常。套接字也将只接收从指定地址和端口发送来的数据报文,从其他地址或端口发送来的数据报文将被忽略。
disconnect()方法用来清空远程地址和端口号,若存在的话。close()方法表明该套接字不再使用
DatagramSocket: 地址处理
InetAddress getInetAddress()
int getPort()
SocketAddress getRemoteSocketAddress()
InetAddress getLocalAddress()
int getLocalPort()
SocketAddress getLocalSocketAddress()
DatagramSocket: 发送和接收
void send(DatagramPacket packet)
void receive(DatagramPacket packet)
DatagramSocket: 选项
int getSoTimeout()
void setSoTimeout(int timeoutMillis)