一、概念
在TCP的所有操作中都必须建立可靠的连接,这样一来肯定会浪费大量的系统性能,为了减少这种开销,在网络中又提供了另外的一种传输协议——UDP,不可靠的连接(这种协议在各种聊天工具中被广泛使用)。
在UDP程序的开发中使用DatagramPacket包装一条要发送的信息,之后使用DatagramSocket用于完成信息的发送操作。
例如:现在使用聊天工具进行聊天,那么A发送的信息B不一定能够接收的到,因为使用的就是UDP协议。
基于UDP通信的基本模式:
(1)将数据打包,称为数据包(好比将信件装入信封一样),然后将数据包发往目的地。
(2)接受别人发来的数据包(好比接收信封一样),然后查看数据包中的内容。
以下用一个聊天程序来说明,功能效果如下图所示:
二、工程目录
三、服务端
1)UDPServer类,服务端主类
importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;importjavax.swing.ImageIcon;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JOptionPane;importjavax.swing.JPanel;importjavax.swing.JTextArea;importjavax.swing.JTextField;public class UDPServer extends JFrame implementsActionListener{
JTextArea jta;
JTextField jtf;
JButton jb;
JPanel jp;
ServerToClientThread stcT;public static voidmain(String[] args) {//TODO Auto-generated method stub
newUDPServer();
}publicUDPServer()
{
setTitle("UDP服务端");
jta=newJTextArea();
jtf=new JTextField(15);
jb=new JButton("发送");
jb.addActionListener(this);
jp=newJPanel();
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= newServerToClientThread(jta);
stcT.start();/**窗体关闭按钮事件*/
this.addWindowListener(newWindowAdapter()
{public voidwindowClosing(WindowEvent e)
{if(JOptionPane.showConfirmDialog(null, "确定退出吗?","系统提示",JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE)==0)
{
System.exit(0);
stcT.closeSocket();
}else{return;
}
}
});
}
@Overridepublic voidactionPerformed(ActionEvent arg0) {//TODO Auto-generated method stub//假如点击了按钮jb
if(arg0.getSource()==jb)
{byte buffer[] =jtf.getText().trim().getBytes();
stcT.sendData(buffer);
}
}
}
2)ServerToClientThread类,服务端处理线程
importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importjavax.swing.JTextArea;/***@authorlenovo
**/
public class ServerToClientThread extendsThread{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;//构造函数
publicServerToClientThread(JTextArea jta) {this.jta =jta;
}public voidrun() {try{
inBuf= new byte[BUFFER_SIZE];
receivePacket= newDatagramPacket(inBuf,inBuf.length);
receiveSocket= newDatagramSocket(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+"\n");
}catch(Exception e) {
e.printStackTrace();//TODO: handle exception
}
}
}
}public void sendData(bytebuffer[]){try{
InetAddress address=InetAddress.getByName(sendIP);//outBuf = new byte[BUFFER_SIZE];
sendPacket = newDatagramPacket(buffer,buffer.length,address,sendPORT);
sendSocket= newDatagramSocket();
sendSocket.send(sendPacket);
}catch(Exception e) {
e.printStackTrace();//TODO: handle exception
}
}public voidcloseSocket(){
receiveSocket.close();
}
}
三、客户端
1)UDPClient类,客户端主类
importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JOptionPane;importjavax.swing.JPanel;importjavax.swing.JTextArea;importjavax.swing.JTextField;public class UDPClient extends JFrame implementsActionListener{
JTextArea jta;
JTextField jtf;
JButton jb;
JPanel jp;
ClientToServerThread ctsT;public static voidmain(String[] args) {//TODO Auto-generated method stub
newUDPClient();
}publicUDPClient()
{
setTitle("UDP客户端");
jta=newJTextArea();
jtf=new JTextField(15);
jb=new JButton("发送");
jb.addActionListener(this);
jp=newJPanel();
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= newClientToServerThread(jta);
ctsT.start();/**窗体关闭按钮事件*/
this.addWindowListener(newWindowAdapter()
{public voidwindowClosing(WindowEvent e)
{if(JOptionPane.showConfirmDialog(null, "确定退出吗?","系统提示",JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE)==0)
{
System.exit(0);
ctsT.closeSocket();
}else{return;
}
}
});
}
@Overridepublic voidactionPerformed(ActionEvent arg0) {//TODO Auto-generated method stub//假如点击了按钮jb
if(arg0.getSource()==jb)
{byte buffer[] =jtf.getText().trim().getBytes();
ctsT.sendData(buffer);
}
}
}
2)ClientToServerThread类,客户端线程处理类
importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importjavax.swing.JTextArea;/***@authorlenovo
**/
public class ClientToServerThread extendsThread{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;//构造函数
publicClientToServerThread(JTextArea jta) {this.jta =jta;
}public voidrun() {try{
inBuf= new byte[BUFFER_SIZE];
receivePacket= newDatagramPacket(inBuf,inBuf.length);
receiveSocket= newDatagramSocket(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+"\n");
}catch(Exception e) {
e.printStackTrace();//TODO: handle exception
}
}
}
}public void sendData(bytebuffer[]){try{
InetAddress address=InetAddress.getByName(sendIP);
sendPacket= newDatagramPacket(buffer,buffer.length,address,sendPORT);//注意发送的时候,socket不需要绑定地址
sendSocket = newDatagramSocket();
sendSocket.send(sendPacket);
}catch(Exception e) {
e.printStackTrace();//TODO: handle exception
}
}public voidcloseSocket(){
receiveSocket.close();
}
}