牛骨文教育服务平台(让学习变的简单)
package com.sjf;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
 * @time 2015-05-27
 * @desc UDP通信
 * @author sjf0115
 *
 */
public class Server {    

    private byte[] buffer = new byte[1024];    
    private DatagramSocket socket = null;    
    private DatagramPacket packet = null;    
    private InetSocketAddress socketAddress = null;    
    private InetAddress clientAddress;
    private String clientIP;
    private int clientPort;
    private String clientData;

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 构造函数,绑定主机和端口.  
     * @param ip  IP 地址
     * @param port 端口  
     * @throws Exception  
     */    
    public Server(String ip, int port) throws Exception 
    {    
        // 绑定IP地址和端口. 
        Bind(ip,port); 
        System.out.println("[服务端启动]");    
    }
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public Server() throws SocketException
    {
        // 构造数据报套接字并将其绑定到本地主机上任何可用的端口
        socket = new DatagramSocket();    
        System.out.println("[服务端启动]");    
    }
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 绑定监听地址和端口.  
     * @param ip IP地址  
     * @param port 端口  
     * @throws SocketException  
     */    
    public void Bind(String ip, int port) throws SocketException {    
        // 根据 IP 地址和端口号创建套接字地址
        socketAddress = new InetSocketAddress(ip, port);  
        // 创建数据报套接字,将其绑定到指定的本地地址
        socket = new DatagramSocket(socketAddress);
        packet = new DatagramPacket(buffer, buffer.length);
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public final String getOrgIp() 
    {    
        return clientIP;    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 设置超时时间  
     * @param timeout 超时时间  
     * @throws Exception  
     */    
    public void SetTimeout(int timeout) throws Exception 
    {    
        /* 启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。
         * 将此选项设为非零的超时值时,对此 DatagramSocket 调用 receive() 将只阻塞此时间长度。
         * 如果超过超时值,将引发 java.net.SocketTimeoutException,虽然 DatagramSocket 仍旧有效。
         * 选项必须在进入阻塞操作前被启用才能生效。
         */
        socket.setSoTimeout(timeout);    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 获得超时时间.  
     * @return 返回超时时间.  
     * @throws Exception  
     */    
    public int GetTimeout() throws Exception 
    {    
        return socket.getSoTimeout();    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 接收数据包,该方法会造成线程阻塞.  
     * @return 返回接收的数据串信息  
     * @throws IOException   
     */    
    public String Receive() throws IOException 
    {    
        /*
         * 从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。
         * 数据报包也包含发送方的 IP 地址和发送方机器上的端口号。此方法在接收到数据报前一直阻塞。
         * 数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短。
         */
        socket.receive(packet);
        // 数据报包包含发送方的 IP 地址
        clientAddress = packet.getAddress();
        clientIP = clientAddress.getHostAddress();
        // 数据报包包含发送方的端口号
        clientPort = packet.getPort();
        // 数据报包包含发送方的数据
        clientData = new String(packet.getData(), 0, packet.getLength());     
        return " ["+clientData+"]";    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 将响应包发送给请求端.  
     * @param bytes 回应报文  
     * @throws IOException  
     */    
    public void Send(String info) throws IOException 
    {    
        packet.setAddress(clientAddress);
        packet.setPort(clientPort);
        packet.setData(info.getBytes()); 
        /*
         * 从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
         */
        socket.send(packet);    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 关闭udp监听口.  
     */    
    public void close() 
    {    
        try 
        {    
            socket.close();    
        } 
        catch (Exception ex) 
        {    
            ex.printStackTrace();    
        }    
    }    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**  
     * 测试方法.  
     * @param args  
     * @throws Exception  
     */    
    public static void main(String[] args) throws Exception {    
        String serverHost = "127.0.0.1";    
        int serverPort = 3344;    
        Server udpServerSocket = new Server(serverHost, serverPort);    
        while (true) 
        {    
            String info = udpServerSocket.Receive();  
            System.out.println("["+udpServerSocket.clientPort+"]->"+info);
            udpServerSocket.Send("Reponse-----"+info);    
        }    
    }    
}   
package com.sjf;

import java.io.*;  
import java.net.*;  

/** 
 * @time 2015-05-27
 * @desc UDP通信
 * @author QPING
 */  
public class Client {  

    private byte[] buffer = new byte[1024];  
    private DatagramSocket socket = null;  
    private InetSocketAddress socketAddress = null;    
    private String clientIP;
    private int clientPort;
    private String clientData;
    private InetAddress clientAddress;
    private DatagramPacket sendPacket;
    private DatagramPacket receivePacket;
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public Client(String host, int port) throws Exception 
    {    
         // 根据 IP 地址和端口号创建套接字地址
        socketAddress = new InetSocketAddress(host, port);  
        // 创建数据报套接字,将其绑定到指定的本地地址
        socket = new DatagramSocket(socketAddress);    
        System.out.println("服务端启动!");    
    }
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 构造函数,创建UDP客户端 
     * @throws Exception 
     */  
    public Client() throws Exception 
    {  
        socket = new DatagramSocket();  
    }  
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
    /** 
     * 设置超时时间,该方法必须在bind方法之后使用. 
     * @param timeout 超时时间 
     * @throws Exception 
     */  
    public final void SetTimeout(final int timeout) throws Exception 
    {  
        socket.setSoTimeout(timeout);  
    }  
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 获得超时时间. 
     * @return 返回超时时间 
     * @throws Exception 
     */  
    public int GetTimeout() throws Exception 
    {  
        return socket.getSoTimeout();  
    }
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public DatagramSocket GetSocket() 
    {  
        return socket;  
    }  
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 向指定的服务端发送数据信息. 
     * @param ip 服务器主机地址 
     * @param port 服务端端口 
     * @param bytes 发送的数据信息 
     * @return 返回构造后俄数据报 
     * @throws IOException 
     */  
    public DatagramPacket Send(String ip,int port,String info) throws IOException 
    {  
        byte[] bytes = info.getBytes();
        sendPacket = new DatagramPacket(bytes, bytes.length);
        sendPacket.setAddress(InetAddress.getByName(ip));
        sendPacket.setPort(port);
        socket.send(sendPacket);  
        return sendPacket;  
    }  
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 接收从指定的服务端发回的数据. 
     * @param lhost 服务端主机 
     * @param lport 服务端端口 
     * @return 返回从指定的服务端发回的数据. 
     * @throws Exception 
     */  
    public String Receive(String lhost,int lport)   throws Exception 
    {  
        receivePacket = new DatagramPacket(buffer, buffer.length);  
        socket.receive(receivePacket);  
        // 数据报包包含发送方的 IP 地址
        clientAddress = receivePacket.getAddress();
        clientIP = clientAddress.getHostAddress();
        // 数据报包包含发送方的端口号
        clientPort = receivePacket.getPort();
        // 数据报包包含发送方的数据
        clientData = new String(receivePacket.getData(), 0, receivePacket.getLength());     
        return "["+clientData+"]"; 
    }  
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 关闭udp连接. 
     */  
    public void close() 
    {  
        try 
        {  
            socket.close();  
        } 
        catch (Exception ex) 
        {  
            ex.printStackTrace();  
        }  
    }  
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** 
     * 测试客户端发包和接收回应信息的方法. 
     * @param args 
     * @throws Exception 
     */  
    public static void main(String[] args) throws Exception {  

        String serverHost = "127.0.0.1";  
        int serverPort = 3344;

        String myIP = "127.0.0.2";
        int myPort = 3333;

        Client client = new Client(myIP,myPort);  
        while(true)
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("["+myPort+"] ");
            String str = br.readLine();

            client.Send(serverHost, serverPort, str);

            String info = client.Receive(serverHost, serverPort);  
            System.out.println("["+client.clientPort+"]->" + info);  
        }
    }  
}