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();
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM