java的BIO实现

来源:互联网 发布:网络社会组织 编辑:程序博客网 时间:2024/05/19 16:06

概述

       该篇博客主要讲解BIO的使用,以及使用中存在一些问题。


单线程处理

package one;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;/** * BIO服务端 */public class BioService1 {    public static void main(String[] args) throws IOException {        ServerSocket serverSocket = new ServerSocket(10101);        System.out.println("服务器启动!");        while (true){            //获取一个套接字(阻塞)            final Socket socket = serverSocket.accept();            System.out.println("来了一个新客户端!");            //业务处理            handler(socket);        }    }    /**     * 读取数据     * @param socket     */    private static void handler(Socket socket){        try{            byte[] bytes = new byte[1024];            InputStream inputStream = socket.getInputStream();            while (true){                //读取数据 阻塞                int read = inputStream.read(bytes);                if(read != -1){                    System.out.println(new String(bytes,0,read));                }else{                    break;                }            }        }catch (Exception ex){            ex.printStackTrace();        }finally {            try{                System.out.println("socket关闭");                socket.close();            }catch (Exception ex){                ex.printStackTrace();            }        }    }}
        本实例是一个简单的BIO的实现,在这里需要说明几个点阻塞点,一个是获取相应的套接字时,一个是读取数据时,通过运行该程序,使用telnet工具可以证实。

        上面的demo中存在的问题,运行该demo,通过telnet测试可知,该服务端一次只能接收一个客户端的请求,即:服务端接收了一个客户端请求后,服务端阻塞在读数据上时,此时,有另一个客户端请求链接该服务端,服务器端是无法接收该链接的,因为,服务器端只有一个线程,而该线程现已经被阻塞了。要想让服务器端实现同时处理多个客户端的请求,可以通过多线程进行解决。


多线程的处理

package one;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 采用多线程的方式进行处理 */public class BioService2 {    public static void main(String[] args) throws IOException {        ExecutorService newCashedThreadPool = Executors.newCachedThreadPool();        ServerSocket serverSocket = new ServerSocket(10101);        System.out.println("服务器启动!");        while (true){            //获取一个套接字(阻塞)            final Socket socket = serverSocket.accept();            System.out.println("来了一个新客户端!");            newCashedThreadPool.execute(new Runnable() {                @Override                public void run() {                    //业务处理                    handler(socket);                }            });        }    }    /**     * 读取数据     * @param socket     */    private static void handler(Socket socket){        try{            byte[] bytes = new byte[1024];            InputStream inputStream = socket.getInputStream();            while (true){                //读取数据 阻塞                int read = inputStream.read(bytes);                if(read != -1){                    System.out.println(new String(bytes,0,read));                }else{                    break;                }            }        }catch (Exception ex){            ex.printStackTrace();        }finally {            try{                System.out.println("socket关闭");                socket.close();            }catch (Exception ex){                ex.printStackTrace();            }        }    }}

        该服务器端每次接收到一个客户端链接时,就会创建一个线程进行业务处理,即:每个链接都会有单独的一个线程进行为它服务。这种方式是非常消耗资源的,这种方式要求的链接都是短连接,通过这种要求,来使每个链接占用的线程的时间缩减到最小,从而可以进行更多的链接处理。


总结

        单线程的服务器端,每次只能处理一个客户端请求;多线程的服务器端,将接收客户端链接和业务分开,将业务处理使用多线程,从而达到可以处理多个客户单请求,即:一个客户端一个线程,这种方式非常的消耗资源。

        这里需要强调一下,服务端拿客户端的请求的链接,都是从tcp的链接缓存区里面拿的,当然,缓存区可以缓存多少链接数,这些参数也都是可以设置。

原创粉丝点击