java 网络编程基础 UDP协议DatagramSocket,MulticastSocket 实现局域网聊天软件(Server + Client模式)

 

 

 

开发思路:
服务端两个Socket:
  1. UDP的DatagramSocket接收客户端消息。
  2. 广播multicastSocket 发送广播消息

客户端一个Socket:

  1. multicastSocket 接收服务端发来的广播 (不允许客户端直接发广播),同时发送点对点数据到UDP服务端DatagramSocket 。
  2. javax.swing.* 提供客户端图形化界面

生疏知识点:

图形化界面按钮监控键盘

addActionListener(AbstractAction接口实现类);监听器。
topTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"confirm_username"); 键盘事件和名字关联;
topTextField.getActionMap().put("confirm_username",confirmListener); 事件别名和监听器关联
服务器端程序:
package tcpandudp.udpexample;

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

/**
 * @ClassName MulticastServerScoket
 * @projectName: object1
 * @author: Zhangmingda
 * @description: 设计思想:为避免所有人直接发广播,导致消息内容无环节把控,消息发送的时候,发送到非广播端口(作为一个服务端)再由此服务端向广播地址发送消息,
 * date: 2021/5/13.
 */
public class MulticastServerScoket {
    /**
     * 广播Socket端口
     */
    private static final int BROAD_PORT = 30000;
    /**
     * 广播IP地址 :224.0.0.0 到 239.255.255.255
     */
    private static final String BROAD_IP = "230.3.3.3";
    /**
     * 服务端口
     */
    private static final int SERVER_PORT = 8888;
    private void start(){
        try (
                /**
                 * 广播用套接字
                 */
                MulticastSocket multicastSocket = new MulticastSocket(BROAD_PORT);
                 /**
                  * 服务端套接字
                  */
                 DatagramSocket datagramSocket = new DatagramSocket(SERVER_PORT)
        ){
            /**
             * 广播IP地址
             */
            InetAddress multi_addr = InetAddress.getByName(BROAD_IP);
            /**
             * 广播套接字配置接收广播的IP地址
             */
            multicastSocket.joinGroup(multi_addr);
            /**
             * 构建接收UDP数据的包
             */
            byte[] inBuff = new byte[4096];
            DatagramPacket inPacket = new DatagramPacket(inBuff,inBuff.length);
            /**
             * 接收广播,并广播出去
             */
            while (true){
                //普通套接字收广播
                datagramSocket.receive(inPacket);

                String content = new String(inPacket.getData(),0,inPacket.getLength());
                System.out.println(content);
                //广播套接字发广播
                DatagramPacket outPacket = new DatagramPacket(inPacket.getData(),inPacket.getLength(),multi_addr,BROAD_PORT);
                multicastSocket.send(outPacket);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 程序入口
     */
    public static void main(String[] args) {
        new MulticastServerScoket().start();
    }
}

客户端

package tcpandudp.udpexample;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @ClassName MulticastClientSocket
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/13.
 */
public class MulticastClientSocket {
    /**
     * 广播Socket端口
     */
    private static final int BROAD_PORT = 30000;
    /**
     * 广播IP地址 :224.0.0.0 到 239.255.255.255
     */
    private static final String BROAD_IP = "230.3.3.3";

    /**
     * 要发送数据包的服务端IP地址和 端口
     */
    private static final String SERVER_IP = "127.0.0.1";
    private static final int    SERVER_PORT = 8888;

    private void go() {
        JFrame jFrame = new JFrame("广播聊天客户端");
        //上部
        JPanel topPanel = new JPanel();
        JTextField topTextField = new JTextField(30);
        JButton topButton = new JButton("确认用户名");
        topPanel.add(topTextField);
        topPanel.add(topButton);
        jFrame.add(topPanel, BorderLayout.NORTH);
        //中部
        JTextArea centerArea = new JTextArea(10,40);
        JScrollPane centerPane = new JScrollPane(centerArea);
        jFrame.add(centerPane);
        //
        JPanel bottomPanel = new JPanel();
        JTextField bottomTextField = new JTextField(35);
        JButton sendButton = new JButton("发送");
        bottomPanel.add(bottomTextField);
        bottomPanel.add(sendButton);
        jFrame.add(bottomPanel, BorderLayout.SOUTH);

        jFrame.setLocation(400,300);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
        AtomicReference<String> username = new AtomicReference<>("");
        //确认用户名事件监听器
        Action confirmListener = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                String topTextContent = topTextField.getText();
                if (topTextContent != null && ! "".equals(topTextContent)){
                    username.set(topTextContent);
                    System.out.println("用户名设置成功");
                }
            }
        };
        //绑定事件监听器
        topButton.addActionListener(confirmListener);
        topTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"confirm_username");
        topTextField.getActionMap().put("confirm_username",confirmListener);
        /**
         * 发送&接收用socket
         */
        try{
            MulticastSocket mClinetSocket = new MulticastSocket(BROAD_PORT);
            InetAddress multi_addr = InetAddress.getByName(BROAD_IP);
            /**
             * 接收端
             */
            new Thread(){
                @Override
                public void run() {
                    byte[] inBuff = new byte[4096];
                    /**
                     * 构建接收包
                     */
                    DatagramPacket inPacket = new DatagramPacket(inBuff,0,inBuff.length);
                    while (true){
                        /**
                         * 接收数据放包里,转为字符串打印出来
                         */
                        try {
                            mClinetSocket.receive(inPacket);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        String content = new String(inPacket.getData(),0, inPacket.getLength());
                        System.out.println(content);
                        centerArea.append(content + "\n"); //向文本框加入文本
                    }
                }
            }.start();
            /**
             * 套接字加入广播地址
             */
            mClinetSocket.joinGroup(multi_addr);

            /**
             * 服务端地址构建
             */
            InetAddress server_addr = InetAddress.getByName(SERVER_IP);
            /**
             * 构建发出包
             */
            DatagramPacket outPacket = new DatagramPacket(new byte[0],0,server_addr,SERVER_PORT);
            /**
             * 发送按钮监听器
             */
            Action sendListener = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    if (username.get().equals("")){
                        System.err.println("请输入用户名");
                    }else {
                        String sendContent = bottomTextField.getText();
                        if (sendContent != null && ! "".equals(sendContent)){
                            sendContent = username + ":" + sendContent;
                            //输入字节存入包,
                            outPacket.setData(sendContent.getBytes());
                            try {
                                mClinetSocket.send(outPacket);
                                bottomTextField.setText(null);
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            };
            /**
             * 发送按钮绑定监听器
             */
            sendButton.addActionListener(sendListener);
            //内容框监听键盘
            bottomTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"send");
            bottomTextField.getActionMap().put("send",sendListener);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        new MulticastClientSocket().go();
    }
}

 

posted on 2021-05-14 23:06  zhangmingda  阅读(474)  评论(0编辑  收藏  举报

导航