• java socket 之UDP编程


    一、概念

            在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();
        }
    }
  • 相关阅读:
    Springboot源码 bean的注册
    Vue源码之 watch
    Vue源码之 slot
    Vue computed 的嵌套
    Vue的子组件绑定的方法中传入自定义参数
    Vue源码之 Vue的生命周期
    Vue源码之-----computed
    Vue源码之----为什么Vue中Array的pop,push等方法可以reactive,而Array[0]='a'这样的方法不会reactive?
    ReSharper 8.1支持Visual Studio 2013的特色——超强滚动条
    Python开发环境Wing IDE使用教程:部分调试功能介绍
  • 原文地址:https://www.cnblogs.com/boshen-hzb/p/5895140.html
Copyright © 2020-2023  润新知