首页 > 代码库 > [java]基于UDP的Socket通信Demo

[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 =http://www.mamicode.com/ recvPacket.getData();                        byte[] recvData = http://www.mamicode.com/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") + "\r\n");                    }                } 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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/ recvPacket.getData();                byte[] recvData = http://www.mamicode.com/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();    }}