带界面的基于UDP传输多人聊天例子

2 篇文章 0 订阅
2 篇文章 0 订阅
package UDP;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

/*
 *
 *需求:编写一个类似qq那样可以聊天的可视化图像界面,实现功能
 *1)用户输入文字可以显示在公共区域(所有人都可以看见)
 * 2015年9月8日
 */

/**
 * 接收显示在公共区域信息的类
 */
class rev_Message implements Runnable {

    MulticastSocket s = null;

    rev_Message(MulticastSocket s) {
        this.s = s;
    }

    @Override
    public void run() {

        while (true) {
            // 2,定义数据包,用于存储数据
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, 0, buf.length);
            try {
                System.out.println("wait connect...");
                // 3,通过Socket的receive方法接收数据
                s.receive(dp);
                // 4,通过数据包的方法提取包中的数据,打印
                System.out.println("ip:" + dp.getAddress().getHostAddress()
                        + "  ||port:" + dp.getPort());
                String str = new String(dp.getData(), 0, dp.getData().length);
                System.out.println("----->data:" + str);
                String str1 = new String("ip:" + dp.getAddress() + "||"
                        + "port:" + dp.getPort());

                createMenu.getTxr_rev().append(
                        "\r\n" + str1 + "\r\n" + str + "\r\n");

            } catch (IOException e) {
                throw new RuntimeException("接收失败");
            }
        }
    }

}

@SuppressWarnings("serial")
class createMenu extends JFrame {

    private JButton btn_clear, btn_send, btn_close, btn_sure;

    private static TextArea txr_send;
    private static TextArea txr_rev;
    private static JTextField txrname;
    private JPanel contentPane1;
    private JDialog dialog;
    private JLabel label;
    MulticastSocket s = null;
    InetAddress group = null;

    createMenu() {
        this.s = UDP_ChatDemo2.s;
        this.group = UDP_ChatDemo2.group;
        init_menu();
        someEvent();

    }


    private void someEvent() {

        btn_send.addActionListener(new SendMsg2(s, group));

        btn_clear.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                txr_send.setText("");

            }
        });
        btn_close.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);

            }
        });
        txr_rev.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                e.consume();// 屏蔽掉法输入
            }
        });
        txr_send.addKeyListener(new SendMsg2(s, group));
        dialog.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                dialog.setVisible(false);
            }

        });
        btn_sure.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                dialog.setVisible(false);
            }

        });
    }

    private void init_menu() {
        setTitle("聊天");
        setBounds(200, 100, 600, 500);// 设置窗体位置和大小

        contentPane1 = new JPanel();// 创建内容面板
        contentPane1.setBorder(new EmptyBorder(5, 5,5, 5));// 设置面板的边框
        setContentPane(contentPane1);// 应用内容面板
        GridBagLayout gbl_contentPane = new GridBagLayout();// 创建网格组布局
        contentPane1.setLayout(gbl_contentPane);// 使用网格组布局

        txr_rev = new TextArea();

        GridBagConstraints gbc_edt_rev = new GridBagConstraints();// 创建网格组布局约束条件
        gbc_edt_rev.insets = new Insets(0, 0, 5, 5);// 设置控件的空白
        gbc_edt_rev.fill = GridBagConstraints.HORIZONTAL;

        gbc_edt_rev.gridwidth = 3;
        gbc_edt_rev.gridheight = 1;

        contentPane1.add(txr_rev, gbc_edt_rev);// 增加显示文本及其约束条件
        
        JPanel panel_send = new JPanel();
    
        txr_send = new TextArea();
        
        JPanel panel_name = new JPanel(new FlowLayout());
        JLabel txtname = new JLabel("名字:");
        txrname = new JTextField(10);
        panel_name.add(txtname);
        panel_name.add(txrname);
        GridBagConstraints gbc_edt_name = new GridBagConstraints();
        gbc_edt_name.fill = GridBagConstraints.HORIZONTAL;// 创建网格组布局约束条件
        gbc_edt_name.gridx = 0;
        gbc_edt_name.gridy = 2;
        gbc_edt_name.gridwidth = 2;
        gbc_edt_name.gridheight =1;
        contentPane1.add(panel_name,gbc_edt_name);
        panel_send.add(txr_send);
        
        GridBagConstraints gbc_edt_send = new GridBagConstraints();// 创建网格组布局约束条件
        gbc_edt_send.fill = GridBagConstraints.HORIZONTAL;

        gbc_edt_send.insets = new Insets(5, 0, 5, 5);// 设置控件的空白
        gbc_edt_send.gridx = 0;
        gbc_edt_send.gridy = 1;
        gbc_edt_send.gridwidth = 3;
        gbc_edt_send.gridheight = 1;
        contentPane1.add(panel_send, gbc_edt_send);

        btn_send = new JButton("发送");
        GridBagConstraints gbc_btn_send = new GridBagConstraints();// 创建网格组布局约束条件
        gbc_btn_send.fill = GridBagConstraints.HORIZONTAL;// 设置填充方式
        gbc_btn_send.weightx = 10.0;// 第三行的分布方式为10%
        gbc_btn_send.insets = new Insets(0, 0, 5, 5);// 设置控件的空白
        gbc_btn_send.gridx = 0;
        gbc_btn_send.gridy = 4;
        contentPane1.add(btn_send, gbc_btn_send);

        btn_clear = new JButton("清除");
        GridBagConstraints gbc_btn_clear = new GridBagConstraints();// 创建网格组布局约束条件
        gbc_btn_clear.fill = GridBagConstraints.HORIZONTAL;// 设置填充方式
        gbc_btn_clear.weightx = 10.0;// 第三行的分布方式为10%
        gbc_btn_clear.insets = new Insets(0, 0, 5, 5);// 设置控件的空白
        gbc_btn_clear.gridx = 1;
        gbc_btn_clear.gridy = 4;

        contentPane1.add(btn_clear, gbc_btn_clear);

        btn_close = new JButton("关闭");
        GridBagConstraints gbc_btn_close = new GridBagConstraints();// 创建网格组布局约束条件
        gbc_btn_close.fill = GridBagConstraints.HORIZONTAL;// 设置填充方式
        gbc_btn_close.weightx = 10.0;// 第三行的分布方式为10%
        gbc_btn_close.insets = new Insets(0, 5, 5, 5);// 设置控件的空白
        gbc_btn_close.gridx = 2;
        gbc_btn_close.gridy = 4;
        contentPane1.add(btn_close, gbc_btn_close);

        dialog = new JDialog(dialog, "提示", true);
        dialog.setBounds(50, 60, 300, 200);
        dialog.setLayout(new FlowLayout());
        btn_sure = new JButton("确定");
        label = new JLabel("              发送数据不为空,请重新输入                   ");
        dialog.add(label);
        dialog.add(btn_sure);

    }

    public static TextArea getTxr_send() {
        return txr_send;
    }

    public static TextArea getTxr_rev() {
        return txr_rev;
    }

    class SendMsg2 implements ActionListener, KeyListener {

        String msg = null;
        MulticastSocket s = null;
        InetAddress group = null;

        public SendMsg2(MulticastSocket s, InetAddress group) {
            this.s = s;
            this.group = group;
        }

        public void actionPerformed(ActionEvent e) {
            sendMsg();

        }

        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == e.VK_ENTER) {
                sendMsg();
            }

        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub

        }

        /**
         * 发送数据
         */
        private void sendMsg() {
            
            // 如果名字为空 给出提示信息
            if(txrname.getText().isEmpty()){
                new JOptionPane().showMessageDialog(null, "请一定要取别名!");
            }
            byte[] buf = new byte[1024];

            String line = txrname.getText() + ": "+txr_send.getText();

            try {
                if (!line.isEmpty()) {

                    System.out.print("input:");
                    buf = line.getBytes();

                    // 2,确定数据,并封装成数据包,里边有对方的ip地址和端口
                    DatagramPacket dp = new DatagramPacket(buf, 0, buf.length,
                            group, 5556);
                    // 3.通过Socket服务,将已有的数据发出去
                    s.send(dp);

                    String str1 = new String("ip:" + dp.getAddress() + "||"
                            + "port:" + dp.getPort());
                    System.out.println("send===>" + str1);
                    txr_send.setText("");
                    line = txr_send.getText();
                } else {
                    System.out.println("发送数据不为空,请重新输入");

                    dialog.setVisible(true);
                }

            } catch (Exception e1) {
                // TODO Auto-generated catch block
                System.out.println("发送失败");
                e1.printStackTrace();
            }

        }
    }
}

public class UDP_ChatDemo2 {

    public static MulticastSocket s = null;
    public static InetAddress group = null;
    public static void main(String[] args) throws Exception {

        // 实现组播数据传送的配置信息
        SetMuticasSocket();

        new createMenu().setVisible(true);
        new Thread(new rev_Message(s)).start();

    }

    /**
     * 实现组播数据传送的配置信息
     */
    private static void SetMuticasSocket() {
        // TODO Auto-generated method stub

        try {

        //IP网络的组播一般通过组播IP地址来实现。组播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。

            group = InetAddress.getByName("228.9.6.12");
        } catch (UnknownHostException e1) {
            System.out.println("组播地址绑定失败");
        }
        try {
            s = new MulticastSocket(5556);
        } catch (IOException e1) {
            System.out.println("组播地址创建失败");
        }
        try {
            s.joinGroup(group);
        } catch (IOException e1) {
            System.out.println("组播地址加入失败");
        }

    }

}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于UDP多人聊天设计可以通过以下步骤来实现。 首先,进行网络连接的建立。在客户端,创建一个UDP套接字,并指定服务器的IP地址和端口号,然后将客户端的套接字绑定到一个固定的本地IP地址和端口。在服务器端,创建一个UDP套接字,并将服务器端的套接字绑定到一个指定的IP地址和端口。 接下来,客户端可以向服务器发送连接请求。客户端发送一个连接请求数据包到服务器,并等待服务器的响应。如果服务器接受了连接请求,则返回一个确认连接的响应给客户端。 在聊天过程中,客户端可以通过套接字发送消息给服务器,服务器将接收到的消息转发给所有其他客户端。客户端可以通过接收套接字接收消息,并将其显示在用户界面上。 为了实现多人聊天功能,服务器需要维护一个客户端列表,用于记录所有连接到服务器的客户端。当有新的客户端连接到服务器时,服务器将将其添加到客户端列表中。当服务器接收到一个消息时,它将遍历客户端列表,并将消息发送给每个客户端。 为了确保消息的可靠传递,可以在发送消息时添加一些消息头,包含发送者的信息、消息的类型等。接收方可以根据消息头来解析消息,并作出相应的处理。 此外,为了实现并发处理,可以使用多线程的方式。每个客户端连接到服务器时,服务器将创建一个新的线程来处理该客户端的消息。这样可以避免阻塞其他客户端的消息传递。 总结起来,基于UDP多人聊天设计包括网络连接建立、消息传递、客户端列表维护、并发处理等步骤,通过这些步骤的实现,可以实现一个简单的基于UDP多人聊天系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值