美文网首页Java网络编程
Java网络编程模型(一)

Java网络编程模型(一)

作者: Super昕 | 来源:发表于2019-02-12 17:51 被阅读0次

    本系列主要介绍java网络编程的模型,沿着模型的进化线结合案例分析学习。本文主要介绍基于OIO的网络编程模型。

基于BIO(OIO)的网络编程模型

    BIO(OIO)是指阻塞输入输出流(旧输入输出流),基于阻塞输入输出流的网络编程初始具有以下特点:
1、服务端启动后会阻塞直到监测到有客户端连接;
2、客户端发起连接请求,获取输入流读取数据,如果没有数据可读取将会一直处于阻塞状态;
3、所有连接处理都在一个线程中进行,因此在连接数较多时,连接请求需要排队等候;

案例——服务端:

package javanio.oionet;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
/**
 * @author 54353
 * OIO网络模型服务端:
 * 向客户端写入服务端接收时间
 */
public class TestServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket=new ServerSocket(12121)){
            while(true) {//1 循环等待连接
                //2 accept()阻塞直到有连接进来,返回对等端socket对象
                Socket client=serverSocket.accept();
                System.out.println("接收到客户端请求!!");
                Writer bWriter=new OutputStreamWriter(client.getOutputStream(),"ASCII");
                Date date=new Date();
                //3 输出流中写入时间
                while(true) {//确保任务不停进行
                    bWriter.write(date.toString()+'\r'+'\n');
                    //4 确保数据写入
                    bWriter.flush();
                    System.out.println("数据传输完成!");
                }
            }
        } catch (Exception e) {
            System.out.println("端口可能被占用!");
        }
    }
}

案例——客户端

package javanio.oionet;

import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class TestClient2 {

    public static void main(String[] args) {
        Socket socket=null;
        try {
            socket=new Socket("127.0.0.1", 12121);
            InputStreamReader reader=new InputStreamReader(socket.getInputStream(),"ASCII");
            System.out.println("读取服务端传送过来的数据!");
            for(int c=reader.read();c!=-1;c=reader.read()) {
                System.out.print((char)c);
            }
        } catch (UnknownHostException e) {
            System.out.println("请求的主机地址不存在!");
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (socket!=null) {
                try {
                    socket.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
    }

}

    这里客户端同样的demo有三个,启动服务端,启动客户端后,服务端输出结果如下:


server.png

客户端2输出结果如下:


client2.png

客户端3输出结果如下:


client3.png

    TestClient2,TestClient3启动后,TestClient2不断输出服务端写入的时间,TestClient3却没有输出任何的时间数据。这是因为所有客户端连接共享一个服务端线程,服务端在不断向TestClient2输出数据,TestClient3必须等到TestClient2的请求结束,服务端向其输出数据后才能输出时间数据。这也是本文一开始提到的第三个特点。
针对这种模式存在的缺陷,基于OIO提出了多线程的模型,也即是服务端针对每一个请求开启一个新的线程去处理数据:
服务端的改进:

package javanio.oionet;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
/**
 * @author 54353
 * OIO网络模型服务端:
 * 向客户端写入服务端接收时间
 */
public class TestServer2 {
    
     static class  Task implements Runnable{
          private Socket client;
          public Task(Socket client) {
            this.client=client;
            }
        @Override
        public void run() {
            System.out.println("接收到客户端请求!!");
            Writer bWriter;
            try {
                bWriter = new OutputStreamWriter(client.getOutputStream(),"ASCII");
                Date date=new Date();
                //4 输出流中写入时间
                while(true) {//任务不断进行
                    bWriter.write(date.toString()+'\r'+'\n');
                    //5 确保数据写入
                    bWriter.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
         
     }

    public static void main(String[] args) {
        try (ServerSocket serverSocket=new ServerSocket(12122)){
            while(true) {//1 循环等待连接
                //2 accept()阻塞直到有连接进来,返回对等端socket对象
                Socket client=serverSocket.accept();
                //3 一旦有连接进来,开启新的线程处理连接
                new Thread(new Task(client)).start();
            }
        } catch (Exception e) {
            System.out.println("端口可能被占用!");
        }
    }

}

    在运用多线程处理连接后,输出结果下:
服务端输出


server2.png

几个客户端输出结果相同


client2.png
client3.png

    由此可见,运用多线程OIO模型可以解决,多请求同时发生时的排队等候问题,可以带来更好的客户体验。但是如果线程数过多,对内存的消耗大,同时线程数过多,线程轮转带来的消耗也会非常大,因此肆无忌惮的使用多线程去处理并发请求问题只能算是一种蛮干,对于高并发场景,更是会带来灾难性危害。

关于Reactor模式

    Reactor模式也即响应模式,就本文所涉及的网络编程而言,只有获取到客户端的连接请求后,服务端才执行后续的程序。对于OIO阻塞输入输出流,显然还存在一个明显缺陷:如果一直未接收到客户端请求,服务端一直处于阻塞状态,后面与接入无关的代码也需要等待,这显然会浪费很多的CPU时间,因此从这点考虑,多线程的OIO模式仍存在进步空间。

相关文章

  • Java网络编程模型(一)

    本系列主要介绍java网络编程的模型,沿着模型的进化线结合案例分析学习。本文主要介绍基于OIO的网络编程模型。 基...

  • day26

    1:网络编程(理解)## (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享 (2)网络编程模型 ...

  • java核心类库 —— 网络编程

    java核心类库之-------网络编程体系图 1. 网络概述 1.1网络分层: 1.2网络模型: OSI参考模型...

  • 第62节:探索Java中的网络编程技术

    前言 感谢! 承蒙关照~ 探索Java中的网络编程技术 网络编程就是io技术和网络技术的结合,网络模型的定义,只要...

  • Spider基础之网络编程

    学习自刘大拿的Python课程 网络编程 网络编程 网络协议: 一套规则 网络模型:七层模型-理论模型:任务分块,...

  • UNIX中的五种I/O模型

    在Java网络编程中,应用的较多的主要有BIO,NIO俩种模型,前者为传统的阻塞IO模型,后者为Java1.4后来...

  • Netty学习内容

    java中的几种I/O模型 BIO通信模型 BIO通信模型图 网络编程的基本模型是C/S模型,两个进程之间进行通信...

  • Java网络编程(第四版) PDF 超清版

    《Java网络编程(第四版)》是一本关于Java编程相关的电子书资源,介绍了关于Java、网络编程、Java编程方...

  • 【Java基础】- 网络编程

    网络编程:用Java语言实现计算机间数据的信息传递和资源共享 网络编程模型:计算机网络之间以何种规则进行通信,就是...

  • Java网络编程系列--Socket编程模型

    一、Socket模型 套接字对:由客户端IP、Port和服务端IP、Port组成的四元组(clientaddr:c...

网友评论

    本文标题:Java网络编程模型(一)

    本文链接:https://www.haomeiwen.com/subject/yopheqtx.html