一、概念
在TCP的所有操作中都必须建立可靠的连接,这样一来肯定会浪费大量的系统性能,为了减少这种开销,在网络中又提供了另外的一种传输协议——UDP,不可靠的连接(这种协议在各种聊天工具中被广泛使用)。
在UDP程序的开发中使用DatagramPacket包装一条要发送的信息,之后使用DatagramSocket用于完成信息的发送操作。
例如:现在使用聊天工具进行聊天,那么A发送的信息B不一定能够接收的到,因为使用的就是UDP协议。
基于UDP通信的基本模式:
(1)将数据打包,称为数据包(好比将信件装入信封一样),然后将数据包发往目的地。
(2)接受别人发来的数据包(好比接收信封一样),然后查看数据包中的内容。
以下用一个聊天程序来说明,功能效果如下图所示:
二、工程目录
三、服务端
1)UDPServer类,服务端主类
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class UDPServer extends JFrame implements ActionListener{ JTextArea jta; JTextField jtf; JButton jb; JPanel jp; ServerToClientThread stcT; public static void main(String[] args) { // TODO Auto-generated method stub new UDPServer(); } public UDPServer() { setTitle("UDP服务端"); jta=new JTextArea(); jtf=new JTextField(15); jb=new JButton("发送"); jb.addActionListener(this); jp=new JPanel(); jp.add(jtf); jp.add(jb); this.add(jta,"Center"); this.add(jp,"South"); this.setBounds(300, 200, 300, 200); this.setVisible(true); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); stcT = new ServerToClientThread(jta); stcT.start(); /**窗体关闭按钮事件*/ this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if(JOptionPane.showConfirmDialog(null, "<html>确定退出吗?","系统提示",JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE)==0) { System.exit(0); stcT.closeSocket(); } else { return; } } }); } @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub //假如点击了按钮jb if(arg0.getSource()==jb) { byte buffer[] = jtf.getText().trim().getBytes(); stcT.sendData(buffer); } } }
2)ServerToClientThread类,服务端处理线程
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import javax.swing.JTextArea; /** * @author lenovo * */ public class ServerToClientThread extends Thread{ private String sendIP = "127.0.0.1"; private int sendPORT = 6666; private int receivePORT = 8888; //声明发送信息的数据报套结字 private DatagramSocket sendSocket = null; //声明发送信息的数据包 private DatagramPacket sendPacket = null; //声明接受信息的数据报套结字 private DatagramSocket receiveSocket = null; //声明接受信息的数据报 private DatagramPacket receivePacket = null; //缓冲数组的大小 public static final int BUFFER_SIZE = 5120; private byte inBuf[] = null; //接收数据的缓冲数组 JTextArea jta; // 构造函数 public ServerToClientThread(JTextArea jta) { this.jta = jta; } public void run() { try{ inBuf = new byte[BUFFER_SIZE]; receivePacket = new DatagramPacket(inBuf,inBuf.length); receiveSocket = new DatagramSocket(receivePORT); }catch (Exception e) { e.printStackTrace(); // TODO: handle exception } while (true) { if(receiveSocket == null){ break; } else { try { receiveSocket.receive(receivePacket); String message = new String(receivePacket.getData(),0,receivePacket.getLength()); jta.append("收到数据"+message+" "); } catch (Exception e) { e.printStackTrace(); // TODO: handle exception } } } } public void sendData(byte buffer[]){ try{ InetAddress address = InetAddress.getByName(sendIP); // outBuf = new byte[BUFFER_SIZE]; sendPacket = new DatagramPacket(buffer,buffer.length,address,sendPORT); sendSocket = new DatagramSocket(); sendSocket.send(sendPacket); }catch (Exception e) { e.printStackTrace(); // TODO: handle exception } } public void closeSocket(){ receiveSocket.close(); } }
三、客户端
1)UDPClient类,客户端主类
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class UDPClient extends JFrame implements ActionListener{ JTextArea jta; JTextField jtf; JButton jb; JPanel jp; ClientToServerThread ctsT; public static void main(String[] args) { // TODO Auto-generated method stub new UDPClient(); } public UDPClient() { setTitle("UDP客户端"); jta=new JTextArea(); jtf=new JTextField(15); jb=new JButton("发送"); jb.addActionListener(this); jp=new JPanel(); jp.add(jtf); jp.add(jb); this.add(jta,"Center"); this.add(jp,"South"); this.setBounds(300, 200, 300, 200); this.setVisible(true); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); ctsT = new ClientToServerThread(jta); ctsT.start(); /**窗体关闭按钮事件*/ this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if(JOptionPane.showConfirmDialog(null, "<html>确定退出吗?","系统提示",JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE)==0) { System.exit(0); ctsT.closeSocket(); } else { return; } } }); } @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub //假如点击了按钮jb if(arg0.getSource()==jb) { byte buffer[] = jtf.getText().trim().getBytes(); ctsT.sendData(buffer); } } }
2)ClientToServerThread类,客户端线程处理类
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import javax.swing.JTextArea; /** * @author lenovo * */ public class ClientToServerThread extends Thread{ private String sendIP = "127.0.0.1"; private int sendPORT = 8888; private int receivePORT = 6666; //声明发送信息的数据报套结字 private DatagramSocket sendSocket = null; //声明发送信息的数据包 private DatagramPacket sendPacket = null; //声明接受信息的数据报套结字 private DatagramSocket receiveSocket = null; //声明接受信息的数据报 private DatagramPacket receivePacket = null; //缓冲数组的大小 public static final int BUFFER_SIZE = 5120; private byte inBuf[] = null; //接收数据的缓冲数组 JTextArea jta; // 构造函数 public ClientToServerThread(JTextArea jta) { this.jta = jta; } public void run() { try{ inBuf = new byte[BUFFER_SIZE]; receivePacket = new DatagramPacket(inBuf,inBuf.length); receiveSocket = new DatagramSocket(receivePORT); }catch (Exception e) { e.printStackTrace(); // TODO: handle exception } while (true) { if(receiveSocket == null){ break; } else { try { receiveSocket.receive(receivePacket); String message = new String(receivePacket.getData(),0,receivePacket.getLength()); jta.append("收到数据"+message+" "); } catch (Exception e) { e.printStackTrace(); // TODO: handle exception } } } } public void sendData(byte buffer[]){ try{ InetAddress address = InetAddress.getByName(sendIP); sendPacket = new DatagramPacket(buffer,buffer.length,address,sendPORT); //注意发送的时候,socket不需要绑定地址 sendSocket = new DatagramSocket(); sendSocket.send(sendPacket); }catch (Exception e) { e.printStackTrace(); // TODO: handle exception } } public void closeSocket(){ receiveSocket.close(); } }