• NIO入门之BIO


    传统BIO编程

    网络编程的基本模型是Client-Server模型,也就是两个进程之间相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的端口发起连接请求,通过三次握手建立连接,如果连接成功,双方就可以通过网络套接字(Socket)进行通信。

    在传统的BIO编程中,ServerSocket负责绑定IP地址,启动端口监听,Socket负责发起连接请求,连接成功之后,双方通过输入和输出流进行同步阻塞通信。

    下面通过TimeServer的一个例子,回顾和熟悉BIO编程

    BIO通信模型图


    可以看到再改模型中,有一个Acceptor线程负责监听客户端的连接,并为每个请求创建一个新的线程进行处理。

    我们可以发现该模型最大问题就是缺乏弹性伸缩能力,服务端和客户端线程个数是1比1的关系。

    BIO的TimeServer

    package nio.bio;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * Created by jj on 2018/12/23.
     */
    public class TimeServer {
    
        public static void main(String[] args) throws IOException {
            int port  = 8080;
            if (args != null && args.length >0){
                try{
                    port = Integer.parseInt(args[0]);
                }catch (NumberFormatException e){
    
                }
            }
    
            ServerSocket server = null;
    
            try{
                server = new ServerSocket(port);
                Socket socket = null;
                while (true){
                    socket = server.accept();
                    new Thread(new TimeServerHandler(socket)).start();
                }
            }finally {
                if (server!= null){
                    server.close();
                    server = null;
                }
            }
        }
    }
    

    如果没有客户端请求,则阻塞在server.accept操作上,如果有,则创建一个TimeServerHandler的Runnable线程,处理客户端的Socket链路

    下面,我们看一下TimeServerHandler

    public class TimeServerHandler implements Runnable{
    
        private Socket socket;
    
        public TimeServerHandler(Socket socket) {
            this.socket = socket;
        }
    
    
        public void run() {
            BufferedReader in = null;
            PrintWriter out = null;
            try{
                in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
                out = new PrintWriter(this.socket.getOutputStream(),true);
                String curentTime = null;
                String body = null;
                while (true){
                    body = in.readLine();
                    if (body == null)
                        break;
                    System.out.println("the time server receive order:" + body);
                    curentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(
                            System.currentTimeMillis()
                    ).toString():"BAD ORDER";
                    out.println(curentTime);
                }
            } catch (Exception e) {
                if (in != null){
                    try {
                        in.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if (out != null){
                    out.close();
                    out = null;
                }
                if (this.socket !=null){
                    try {
                        this.socket.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    this.socket = null;
                }
            }
        }
    }
    

    可以看到run中的功能为读取客户端请求,并通过PrintWriter返回给客户端相应。

    下面我们看一下客户端的代码

    public class TimeClient {
    
        public static void main(String[] args) throws IOException {
            int port = 8080;
            if (args != null && args.length > 0) {
                try {
                    port = Integer.parseInt(args[0]);
                } catch (NumberFormatException e) {
    
                }
            }
            Socket socket = null;
            BufferedReader in = null;
            PrintWriter out = null;
            try{
                socket = new Socket("127.0.0.1",port);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(),true);
                out.println("QUERY TIME ORDER");
                
                String resp = in.readLine();
                System.out.print(resp);
    
            }finally {
                if (out != null){
                    out.close();
                    out = null;
                }
                if (in != null){
                    in.close();
                    in = null;
                }
                if (socket != null){
                    socket.close();
                    socket = null;
                }
            }
        }
    }
    
  • 相关阅读:
    Java类 初始化块
    Java中 equals和==
    Raft算法
    OLTP与OLAP
    数据库事务机制ACID
    乐观锁和悲观锁
    SparkStreaming + Flume
    如何提高深度睡眠质量,科学解决睡眠问题
    centos 7 下安装mysql 远程连接出现10038错误如何解决
    CentOS 7.0 yum安装Apache、PHP和MySQL
  • 原文地址:https://www.cnblogs.com/junjiang3/p/10163996.html
Copyright © 2020-2023  润新知