java bio 之聊天室

最近在复习java io相关知识 ,发现很多细节之前没学习到位,原理也没吃透,只能感叹本人愚钝。

复习到bio,顺手写了个简单的聊天室功能,并和大家分享下。

服务端:

package io.QQ聊天室实现_BIO;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class ChartServer {
    public static void main (String[] args) throws IOException {
        ChartServer server = new ChartServer();
        server.init(8889).listener();
    }
    private ServerSocket serverSocket;
    private final List<ProcessorThread> clients = new ArrayList<>();
    public ChartServer init(int port) throws IOException {
        this.serverSocket =new ServerSocket(port);
        return this;
    }
    public void listener() throws IOException {
        //主线程负责监听,启动监听线程
        System.out.println("listener start");
        new Thread(new AcceptThread(serverSocket)).start();
    }

    class AcceptThread implements Runnable{
        private ServerSocket serverSocket;

        public AcceptThread (ServerSocket serverSocket) {
            this.serverSocket = serverSocket;
        }

        @Override
        public void run () {
            while (true){
                try {
                    Socket socket = serverSocket.accept();
                    //子线程负责分发任务
                    new Thread(new ProcessorThread(socket)).start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class ProcessorThread implements Runnable{
        Socket socket;

        public ProcessorThread (Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run () {
            String key = "["+socket.getInetAddress().getHostAddress()+":"+socket.getPort()+"]";
            System.out.println(key+"上线了");
            try {
                writeMsg(socket,key+"上线了");
                clients.add(this);
                readMsg(socket,key);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public String readMsg(Socket socket,String name) throws IOException {

            BufferedReader br =  new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String readLine;
            while (true){
                readLine = br.readLine();
                System.out.println(name+"说:"+readLine);
                writeMsg(socket,name+"说:"+readLine);
            }
        }

        public void writeMsg(Socket socket,String msg) throws IOException {
            //轮询
            OutputStream os;
            for(ProcessorThread s:clients){
                os = s.socket.getOutputStream();
                os.write(msg.getBytes());
                os.write("
".getBytes());
                os.flush();
            }
        }
    }
}

客户端:

package io.QQ聊天室实现_BIO;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class ChartClient {

    private  Socket socket;

    public void init(String host,int port) throws IOException {

        Scanner scanner = new Scanner(System.in);
        socket = new Socket(host,port);
        new Thread(new readThread(socket)).start();
        while (scanner.hasNextLine()){
            String inputStr = scanner.nextLine();
            OutputStream os = socket.getOutputStream();

            OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
            osw.write(inputStr);
            osw.write("
");
            osw.flush();
        }
    }

     class readThread implements Runnable{

        Socket socket;

         InputStream answer ;
         public readThread (Socket socket) throws IOException {
             this.socket = socket;
             answer = socket.getInputStream();
         }

         @Override
         public void run () {
             while (true){
                 BufferedReader br = new BufferedReader(new InputStreamReader(answer));
                 try {
                     StringBuffer sb = new StringBuffer();
                     String readLine;
                     while (true){
                         readLine = br.readLine();
                         sb.append(readLine);
                         System.out.println(readLine);
                     }
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }


    static String host = "127.0.0.1";
    static int port = 8889;
    public static void main (String[] args) throws IOException {
        ChartClient chartClient = new ChartClient();
        chartClient.init(host,port);
    }

}

总结:

  在本例中,最重要的是要理解socket.accept()方法是阻塞的。bio中提供的流写入读取是阻塞的,如inputStream.read 是阻塞的。BufferedReader.readline()的结束标志。

在java网络编程或者java多线程编程中,线程分工是很重要的思想,可以参照tomcat等成熟容器的设计学习。

原文地址:https://www.cnblogs.com/luoluoshidafu/p/8823287.html