1.perface:

   上一章中聊天程序存在着不足如下:

  1. 无法实现多客户端的聊天

  2.客户信息存储问题

  3.服务器转发同步问题:

现在解决如下:见如下代码:

2.service:code:

  client:

class exp_client implements Runnable {
    Socket cs = null;
    String hostName = "localhost";
    int port = 8000;
    DataInputStream is = null;
    static DataOutputStream os = null;
    static  DataInputStream stdIn = null;

    exp_client(String hostName, int port) {
        this.hostName = hostName;
        this.port = port;
    }

    public void run() {
        try {
            cs = new Socket(hostName, port);
            is = new DataInputStream(cs.getInputStream());
            os = new DataOutputStream(cs.getOutputStream());
            stdIn = new DataInputStream(System.in);
            System.out.println("客户端");
            os.writeUTF("你好服务器!");
            os.flush();
            new rcThread(cs).start(); // 启动接收线程
            new scThread(cs).start(); // 启动发送线程
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

2.2 发送和接受线程如下:

class scThread extends Thread { // 自定义发送线程内部类
    Socket client;
    DataOutputStream is = null;
    private DataInputStream stdIn;
    DataOutputStream os = exp_client.os;

    scThread(Socket client) throws Exception {
        this.client = client;
        is = new DataOutputStream(client.getOutputStream());
        stdIn = new DataInputStream(System.in);
    }

    public void run() {
        String str;
        try {
            while (true) {
                str = stdIn.readLine();
                os.writeUTF(client.getInetAddress().toString() + ":"
                        + client.getLocalPort() + ":" + str);
                os.flush();
            }
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
}

2.3 接受线程类:

class rcThread extends Thread { // 自定义接收线程内部类
    Socket client;
    DataInputStream is = null;
    private DataInputStream stdIn=exp_client.stdIn;
    

    rcThread(Socket client) throws Exception {
        this.client = client;
        is = new DataInputStream(client.getInputStream());
    }

    public void run() {
        String str;
        stdIn = new DataInputStream(System.in);
        try {
            while (true) {
                str = is.readUTF();
                System.out.println(str);
            }
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
}

2.4 服务器代码如下:

class MyServer implements Runnable {
    static Vector<Socket> clients = new Vector();
    ServerSocket ss = null;

    MyServer(int port) {
        try {
            ss = new ServerSocket(port); // 端口号唯一标是本进程
            System.out.println("启动本地" + port + "端口");
        } catch (IOException e) {
            System.err.println("启动本地" + port + "端口失败");
            System.exit(1);
        }
    }

    public void run() {
        Socket cs = null;
        try {
            while (true) {
                cs = ss.accept();
                clients.add(cs);
                clientThread ct = new clientThread(cs);
                Thread tct = new Thread(ct);
                tct.start();
            }
        } catch (IOException e) {
            System.err.println(e.toString());
        }
    }

}

2.5 server 线程如下:
class clientThread implements Runnable {
    Socket cs = null;

    clientThread(Socket cs) {
        this.cs = cs;
    }

    public void run() {
        String inputStr, outputStr;
        try {
            DataOutputStream os = new DataOutputStream(cs.getOutputStream());
            DataInputStream is = new DataInputStream(cs.getInputStream());
            DataOutputStream cos = null;

            os.writeUTF("Welcome to My Chat Server");
            os.flush();// 立即将数据从输出缓存提交给网络发送

            while ((inputStr = is.readUTF()) != null) {
                System.out.println("Customer:" + inputStr);
                outputStr = inputStr; // 将接收到的信息转发出去

                for (Socket c : MyServer.clients) {
                    cos = new DataOutputStream(c.getOutputStream());
                    cos.writeUTF(outputStr);
                    cos.flush();
                }
            }
            os.close(); // 流关闭
            is.close();
            cs.close(); // 套接字关闭
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }
}
测试代码:
public class StartClient {

    public static void main(String[] args) {
        exp_client ec = new exp_client("localhost", 8000);
        Thread tec = new Thread(ec);
        try {
            tec.start();
            tec.join();
        } catch (Exception e) {
            System.err.println(e);
        }
    }

}
public class StartServer {

    public static void main(String[] args) {
        MyServer ms = new MyServer(8000);
        Thread tms = new Thread(ms);
        tms.start();
    }
}

3.reference: