zoukankan      html  css  js  c++  java
  • [java]基于UDP的Socket通信Demo

      java课编程作业:在老师给的demo的基础上实现客户端发送数据到服务器端,服务器端接受客户端后进行数据广播。

      整体功能类似于聊天室,代码部分不是太难,但是在本机测试的时候出现这样的问题:

        服务端通过将每一个Socket客户端的IP存入Set集合,每次接受到数据后都向当前所有的IP转发。但是本机演示的时候所有开的ChatClient客户端都是同一IP,怎么测试呢?

      解决办法就是本机测试时候服务端向多个不同的端口转发就好了,这样跑起来的客户端是在不同端口上进行监听的(只是为了实现广播,实际应用下还是通过IP来转发)。

      客户端代码:

      

    import javax.print.attribute.HashPrintServiceAttributeSet;
    import javax.swing.*;
    
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Toolkit;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    
    public class ChatClient extends JFrame {
    
        JTextArea contents = new JTextArea();
        JLabel label1 = new JLabel("服务器地址");
        JTextField address = new JTextField();
        JLabel label2 = new JLabel("用户名");
        JTextField username = new JTextField();
        JButton online = new JButton("上线");
        JButton offline = new JButton("下线");
        JTextField input = new JTextField();
        JButton send = new JButton("发送");
    
        boolean onlineFlag = false;
    
        public ChatClient() {
            super("Chat Client");
    
            contents.setEditable(false);
            getContentPane().add(contents);
    
            JPanel p1 = new JPanel();
            p1.setLayout(new FlowLayout(FlowLayout.LEADING));
    
            address.setPreferredSize(new Dimension(100, 28));
            username.setPreferredSize(new Dimension(80, 28));
            input.setPreferredSize(new Dimension(180, 28));
    
            p1.add(label1);
            p1.add(address);
            p1.add(label2);
            p1.add(username);
            p1.add(online);
            p1.add(offline);
            p1.add(input);
            p1.add(send);
    
            offline.setEnabled(false);
            send.setEnabled(false);
    
            getContentPane().add(p1, BorderLayout.SOUTH);
    
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we) {
                    onlineFlag = false;
                    Map<String, Object> m1 = new HashMap<String, Object>();
                    m1.put("time", new Date()); // 上线时间
                    m1.put("username", getUsername());
                    m1.put("onlineFlag", onlineFlag);
    
                    send(getServerAddress(), 2222, m1);
    
                    System.exit(0);
                }
            });
    
            ActionListener al = new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    String server = getServerAddress();
                    if (server == null || server.length() == 0) {
                        JOptionPane.showMessageDialog(ChatClient.this, "请输入服务器地址!");
                        return;
                    }
    
                    if (ae.getSource() == online) {
                        // 用户点击了上线按钮
                        if (!onlineFlag) {
                            onlineFlag = true;
                            Map<String, Object> m1 = new HashMap<String, Object>();
                            m1.put("time", new Date()); // 上线时间
                            m1.put("username", getUsername());
                            m1.put("onlineFlag", onlineFlag);
                            online.setEnabled(false);
                            offline.setEnabled(true);
                            send.setEnabled(true);
                            address.setEnabled(false);
                            username.setEnabled(false);
                            send(getServerAddress(), 2222, m1);
    
                        }
                    } else {
                        // 用户点击了下线按钮
                        if (onlineFlag) {
                            onlineFlag = false;
                            Map<String, Object> m1 = new HashMap<String, Object>();
                            m1.put("time", new Date()); // 上线时间
                            m1.put("username", getUsername());
                            m1.put("onlineFlag", onlineFlag);
                            online.setEnabled(true);
                            offline.setEnabled(false);
                            send.setEnabled(false);
                            address.setEnabled(true);
                            username.setEnabled(true);
                            send(getServerAddress(), 2222, m1);
                        }
                    }
                }
            };
    
            ActionListener al2 = new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    Map<String, Object> m1 = new HashMap<String, Object>();
                    m1.put("time", new Date());
                    m1.put("username", getUsername());
                    m1.put("input", getInput());
                    send(getServerAddress(), 2222, m1);
                }
            };
    
            send.addActionListener(al2);
    
            online.addActionListener(al);
            offline.addActionListener(al);
    
            // setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(720, 400);
            Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    
            setLocation((d.width - 720) / 2, (d.height - 400) / 2);
            setVisible(true);
    
            new Thread() {
                public void run() {
                    try {
                        // 在2221端口接收服务器发送过来的聊天内容,包括上线,下线消息。
                        DatagramSocket rSocket = new DatagramSocket(2220);
                        while (true) {
                            byte[] buffer = new byte[1024 * 16];
                            DatagramPacket recvPacket = new DatagramPacket(buffer, buffer.length);
                            rSocket.receive(recvPacket);
                            byte[] data = recvPacket.getData();
                            byte[] recvData = new byte[recvPacket.getLength()];
                            System.arraycopy(buffer, 0, recvData, 0, recvData.length);
                            //将从服务器接收的数据存入Map并显示
                            Map<String, Object> map = convertByteArrayToMap(recvData);
                            if (map.containsKey("onlineFlag")) { // 上线或者下线
                                boolean b = (boolean) map.get("onlineFlag");
                                if (b) { // 上线
                                    map.put("input", "上线");
                                } else { // 下线
                                    map.put("input", "下线");
                                }
                            }
                            Date time = (Date) map.get("time");
                            String s = convertDateToFormatString(time);
                            String user = (String) map.get("username");
                            user = "[" + user + "]";
                            contents.append(s + user + ": " + (String) map.get("input") + "
    ");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                }
            }.start();
    
        }
    
        public String getServerAddress() {
            String s = address.getText();
            //trim删除多余空格
            s = s.trim();
            return s;
        }
    
        public String getUsername() {
            String s = username.getText();
            s = s.trim();
            if (s == null || s.length() == 0) {
                s = "匿名";
            }
            return s;
        }
    
        public String getInput() {
            String s = input.getText();
            s = s.trim();
            if (s == null || s.length() == 0) {
                s = "不想说什么";
            }
            return s;
        }
    
        public static String convertDateToFormatString(Date d) {
            return new java.text.SimpleDateFormat("(yyyy-MM-dd HH:mm:ss)").format(d);
        }
    
        public static void send(String ip, int port, Map<String, Object> map) {
            try {
                byte[] data = convertMapToByteArray(map);
                DatagramSocket socket = new DatagramSocket();
                DatagramPacket packet = new DatagramPacket(data, data.length);
    
                packet.setSocketAddress(new InetSocketAddress(ip, port));
                socket.send(packet);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        public static byte[] convertMapToByteArray(Map<String, Object> map) {
            try {
                //完成此代码块,要求将map集合中的数据转换成字节数组
                
                ByteArrayOutputStream b = new ByteArrayOutputStream();
                ObjectOutputStream ois = new ObjectOutputStream(b);
                ois.writeObject(map);
                byte[] temp = b.toByteArray();
                return temp;
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static Map<String, Object> convertByteArrayToMap(byte[] data) {
            try {
                ByteArrayInputStream bais = new ByteArrayInputStream(data);
                ObjectInputStream ois = new ObjectInputStream(bais);
                Map<String, Object> result = (Map<String, Object>) ois.readObject();
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static void main(String[] args) {
            new ChatClient();
        }
    
    }

        服务端代码:

    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    
    import java.util.*;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ChatServer {
    
        LinkedBlockingQueue<Map<String, Object>> queue = new LinkedBlockingQueue<Map<String, Object>>();
        Set<String> onlineIPs = new HashSet<String>(); // 当前在线IP。
    
        public ChatServer() {
            try {
    
                new Thread() {
                    public void run() {
                        while (true) {
                            try {
                                //补齐程序,要求从接收队列中取出数据,遍历在线IP集合,向所有在线IP发送数据
    
                                if( !queue.isEmpty() ){
                                    if( !onlineIPs.isEmpty() ){
                                        for(String ip : onlineIPs){
                                            //下面的端口号可以自定义增加,初始转发至2220端口   多增加的端口可以实现本机内的广播
                                            ChatClient.send(ip, 2221, queue.peek() );
                                            ChatClient.send(ip, 2220, queue.remove() );
                                        }    
                                    }
                                }
                                
                                //end
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
                //接受端口2222
                DatagramSocket serverSocket = new DatagramSocket(2222);
                System.out.println("Chat Server started.");
                while (true) {
                    byte[] buffer = new byte[1024 * 16];
                    DatagramPacket recvPacket = new DatagramPacket(buffer, buffer.length);
    
                    serverSocket.receive(recvPacket);
    
                    InetSocketAddress remoteAddress = new InetSocketAddress(recvPacket.getAddress(),
                            recvPacket.getPort());
                    System.out.println("接收到 " + remoteAddress.getHostString() + " 发送过来的数据包");
    
                    byte[] data = recvPacket.getData();
                    byte[] recvData = new byte[recvPacket.getLength()];
                    System.arraycopy(buffer, 0, recvData, 0, recvData.length);
                    System.out.println(recvData.length);
                    Map<String, Object> map = ChatClient.convertByteArrayToMap(recvData);
                    System.out.print("map长度"+map.size());
                    if (map.containsKey("onlineFlag")) { // 上线或者下线
                        boolean b = (boolean) map.get("onlineFlag");
                        if (b) { // 上线
                            onlineIPs.add(remoteAddress.getHostString());
                        } else { // 下线
                            onlineIPs.remove(remoteAddress.getHostString());
                        }
                    }
    
                    queue.add(map);
    
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new ChatServer();
    
        }
    
    }
  • 相关阅读:
    Oracle关于快速缓存区应用原理
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.RequestContext
    速记const 指针与指向const的指针
    bzoj3992【SDOI2015】序列统计
    ubuntu 1204 安装mysql
    解决getOutputStream() has already been called for this response
    把一个project相关的jar放到project的lib文件夹中
    解决eclipse偶尔无视breakpoint的行为
    解决eclipse无法打开:Failed to load the JNI shared library
    挣值管理公式集合
  • 原文地址:https://www.cnblogs.com/limingxi/p/3822953.html
Copyright © 2011-2022 走看看