java Socket多线程聊天程序

参考JAVA 通过 Socket 实现 TCP 编程

参考java Socket多线程聊天程序(适合初学者)

以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者

服务器端程序:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: 李景然
 * @Date: 2018/5/17 10:12
 * @Description:
 */
public class TKServer extends JFrame implements ActionListener {

    private Map<Integer, Socket> clients = new HashMap<Integer, Socket>();
    private JTextArea msg = new JTextArea("服务器消息接收器\r\n\n");
    private JTextArea input = new JTextArea();
    private JButton msgSend = new JButton("发送群消息");

    public TKServer() {
        // TODO Auto-generated constructor stub
        this.setVisible(true);
        this.setTitle("服务器");
        this.setSize(550, 750);
        this.setResizable(true);
        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);
            }
        });
        input.setColumns(40);
        input.setRows(5);
        input.setAutoscrolls(true);
        msgSend.addActionListener(this);
        msgSend.setActionCommand("sendMsg");
        msg.setAutoscrolls(true);
        msg.setColumns(40);
        msg.setRows(30);

        JScrollPane spanel = new JScrollPane(msg);
        JScrollPane editpanel = new JScrollPane(input);
        this.add(spanel);
        this.add(editpanel);
        this.add(msgSend);
    }

    public static void main(String[] args) {

        new TKServer().listenClient();
    }

    public void listenClient() {

        String temp = "";
        try {
            //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
            // 定义一个ServerSocket监听在端口8899上
            ServerSocket server = new ServerSocket(8899);
            while (true) {
                System.out.println("服务器端正在监听");
                Socket socket = server.accept();
                clients.put(socket.getPort(), socket);
                temp = "客户端" + socket.getPort() + " 连接";
                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())) {
            if ((temp = this.input.getText()) != null) {
                System.out.println("开始向客户端群发消息");
                this.apppendMsg("服务器-->" + temp);
                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 {
                        Writer writer = new OutputStreamWriter(socket.getOutputStream());
                        writer.write(temp);
                        writer.flush();
                    } catch (SocketException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
                this.input.setText("");
            }
        }
    }
}

class mythread extends Thread {

    private Socket socket = null;
    private TKServer server = null;
    private InputStreamReader reader = null;
    char chars[] = new char[64];
    int len;
    private String temp = null;

    public mythread(Socket socket, TKServer 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 = "客户端" + 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();
                }
            }
        }
    }
}

客户端程序:

/**
 * @Auther: 李景然
 * @Date: 2018/5/17 10:15
 * @Description:
 */

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.*;

public class TKClient extends JFrame implements ActionListener {

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

    private JTextArea msg = new JTextArea("客户端消息接收器\r\n\n");
    private JTextArea input = new JTextArea();
    private JButton msgSend = new JButton("发送群消息");

    public TKClient() {
        // TODO Auto-generated constructor stub

        initSocket();
        this.setVisible(true);
        this.setTitle("客户端");
        this.setSize(550, 750);
        this.setResizable(true);
        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 {
        // TODO Auto-generated method stub

        new TKClient();
    }

    public void initSocket() {

        try {
            client = new Socket(this.host, this.port);
            writer = new OutputStreamWriter(client.getOutputStream());
            // 建立连接后就可以往服务端写数据了
            thread = new mythread(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 mythread extends Thread {

    private Socket socket = null;
    private Reader reader = null;
    private int len = 0;
    char chars[] = new char[64];
    private TKClient client = null;
    private String temp = "";

    public mythread(Socket socket, TKClient 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();
            }
        }
    }
}

 

posted on 2018-05-17 12:25  lijingran  阅读(6032)  评论(0编辑  收藏  举报

导航