基于Java Scocket 简单的多线程聊天程序

一个简单的聊天程序,有客户端和服务端,可以进行群聊功能。只有两个文件,涉及Scocket和多线程知识。

话不多说直接上代码

服务器端代码:

/**
 * Created by lean on 2018/7/30.
 */

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Server extends JFrame implements ActionListener{

    private Map<Integer, Socket> clients = new HashMap<Integer, Socket>();
    private JTextArea msg = new JTextArea("消息接收器\r\n");
    private JButton msgSend = new JButton("发送群消息");
    public Server() {
        // TODO Auto-generated constructor stub
        this.setVisible(true);
        this.setSize(500, 650);
        this.setLayout(new FlowLayout());
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent arg0) {
                // TODO Auto-generated method stub
                super.windowClosing(arg0);
                System.exit(0);
            }
        });
        msgSend.addActionListener(this);
        msgSend.setActionCommand("sendMsg");
        msg.setAutoscrolls(true);
        msg.setColumns(40);
        msg.setRows(30);

        JScrollPane spanel = new JScrollPane(msg);
        this.add(spanel);
        this.add(msgSend);
    }
    public static void main(String[] args){
        new Server().listenClient();
    }

    public void listenClient(){
        int port = 8899;
        String temp = "";
        // 定义一个ServerSocket监听在端口8899上
        try {
            ServerSocket server = new ServerSocket(8899);
            // server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
            while (true) {
                System.out.println("服务器端正在监听");
                Socket socket = server.accept();
                temp = "客户端"+socket.getPort()+":连接";
                clients.put(socket.getPort(), socket);
                this.apppendMsg(temp);
                new mythread(socket, this).start();
            }


        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

    }

    public void apppendMsg(String msg){

        this.msg.append(msg+"\r\n");
    }

    public void sendMsgToAll(Socket fromSocket, String msg) {
        Set<Integer> keset = this.clients.keySet();
        java.util.Iterator<Integer> iter = keset.iterator();
        while(iter.hasNext()){
            int key = iter.next();
            Socket socket = clients.get(key);
            if(socket != fromSocket){
                try {
                    if(socket.isClosed() == false){
                        if(socket.isOutputShutdown() == false){

                            Writer writer = new OutputStreamWriter(
                                    socket.getOutputStream());
                            writer.write(msg);
                            writer.flush();
                        }

                    }
                } catch (SocketException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        String temp = "";
        if("sendMsg".equals(e.getActionCommand())){
            System.out.println("开始向客户端群发消息");
            Set<Integer> keset = this.clients.keySet();
            java.util.Iterator<Integer> iter = keset.iterator();
            while(iter.hasNext()){
                int key = iter.next();
                Socket socket = clients.get(key);
                try {
                    if(socket.isClosed() == false){
                        if(socket.isOutputShutdown() == false){
                            temp = "向客户端"+socket.getPort()+"发送消息";
                            System.out.println(temp);
                            Writer writer = new OutputStreamWriter(
                                    socket.getOutputStream());
                            this.apppendMsg(temp);

                            writer.write("来自服务器的问候");
                            writer.flush();
                        }

                    }
                } catch (SocketException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }
    }

}

class mythread extends Thread{

    private Socket socket = null;
    private Server server = null;
    private InputStreamReader reader = null;
    char chars[] = new char[64];
    int len;
    private String temp = null;
    public mythread(Socket socket, Server server) {
        // TODO Auto-generated constructor stub
        this.socket = socket;
        this.server = server;
        init();
    }

    private void init(){
        try {
            reader = new InputStreamReader(socket.getInputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("子线程开始工作");
        while(true){
            try {
                System.out.println("线程"+this.getId()+":开始从客户端读取数据——>");
                while ((len = ((Reader) reader).read(chars)) != -1) {
                    temp = new String(chars, 0, len);
                    System.out.println("来自客户端"+socket.getPort()+"的消息:" +temp);
                    server.apppendMsg("来自客户端"+socket.getPort()+"的消息:" +temp);
                    server.sendMsgToAll(this.socket, "客户端"+socket.getPort()+"的说:" +temp);
                }
                if(socket.getKeepAlive() == false){
                    ((Reader) reader).close();
//                  temp = "线程"+this.getId()+"——>关闭";
//                  System.out.println(temp);
                    temp = "客户端"+socket.getPort()+":退出";
                    server.apppendMsg(temp);
                    socket.close();
                    this.stop();
                }
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                try {
                    ((Reader) reader).close();
                    socket.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

            }
        }
    }
}

客户端代码:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class CKClient extends JFrame implements ActionListener{

    // 为了简单起见,所有的异常都直接往外抛
    String host = "127.0.0.2"; // 要连接的服务端IP地址
    int port = 8899; // 要连接的服务端对应的监听端口
    mythread1 thread  = null;
    Socket client = null;
    Writer writer = null;

    private JTextArea msg = new JTextArea("客户端消息接收器\r\n");
    private JTextArea input = new JTextArea();
    private JButton msgSend = new JButton("发送群消息");
    public CKClient() {
        // TODO Auto-generated constructor stub
        initSocket();
        this.setVisible(true);
        this.setSize(550, 750);
        this.setResizable(false);
        this.setLayout(new FlowLayout());
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent arg0) {
                // TODO Auto-generated method stub
                super.windowClosing(arg0);
                try {
                    if(client != null){
                        client.close();
                    }

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(thread != null){
                    thread.stop();
                }

                System.exit(0);
            }
        });
        input.setColumns(40);
        input.setRows(10);
        input.setAutoscrolls(true);
        msgSend.addActionListener(this);
        msgSend.setActionCommand("sendMsg");
        msg.setAutoscrolls(true);
        msg.setColumns(40);
        msg.setRows(25);
        JScrollPane spanel = new JScrollPane(msg);
        JScrollPane editpanel = new JScrollPane(input);
        this.add(spanel);
        this.add(editpanel);
        this.add(msgSend);
    }
    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        new CKClient();
    }

    public void initSocket(){
        try {
            client = new Socket(this.host, this.port);
            writer = new OutputStreamWriter(client.getOutputStream());
            // 建立连接后就可以往服务端写数据了
            thread = new mythread1(client, this);
            thread.start();
            this.appendMsg("已连上服务器");
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            this.appendMsg("不能连接上服务器");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            this.appendMsg("不能连接上服务器");
        }
    }

    public void appendMsg(String msg){
        this.msg.append(msg+"\r\n");
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        String temp = "";
        try {
            if("sendMsg".equals(e.getActionCommand())){
                if((temp = this.input.getText()) != null){
                    writer.write(temp);
                    writer.flush();
                    this.appendMsg("我("+this.client.getLocalPort()+")说——>"+temp);
                    this.input.setText("");
                }
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

    }

}

class mythread1 extends Thread {
    private Socket socket = null;
    private Reader reader = null;
    private int len = 0;
    char chars[] = new char[64];
    private CKClient client = null;
    private String temp = "";

    public mythread1(Socket socket, CKClient client) {
        // TODO Auto-generated constructor stub
        this.socket = socket;
        this.client = client;
        try {
            reader = new InputStreamReader(socket.getInputStream());
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        System.out.println("客户端子线程"+this.getId()+"开始工作");
        while (true) {
            try {
                if (socket.isClosed() == false) {
                    if (socket.isInputShutdown() == false) {
                        while ((len = ((Reader) reader).read(chars)) != -1) {
                            temp = "服务器说——>"+":"+ new String(chars, 0, len);
                            client.appendMsg(temp);
                            System.out.println();
                        }
                    }

                } else {
                    if (socket.getKeepAlive() == false) {
                        reader.close();
                        socket.close();
                        this.stop();
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/sunayn/article/details/81290099