博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

javaBIO

Posted on 2020-08-16 23:13  kali98k  阅读(90)  评论(0编辑  收藏  举报

Java BIO

一、Java BIO 基本介绍

1.1概念:

Java BIO 就是传统的java io 编程,其相关的类和接口在 java.io

BIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)

1.2应用场景:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,程序简单易理解

二、Java BIO 工作机制

 

 

 

 

BIO编程简单流程

 

1服务器端启动一个ServerSocket

2客户端启动Socket对服务器进行通信,默认情况下服务器端需要对每个客户 建立一个线程与之通讯

 

3客户端发出请求后, 先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝

 

4如果有响应,客户端线程会等待请求结束后,在继续执行

三、Java BIO 应用实例

1使用BIO模型编写一个服务器端,监听6666端口,当有客户端连接时,就启动一个线程与之通讯。

2要求使用线程池机制改善,可以连接多个客户端.

 

(3)服务器端可以接收客户端发送的数据(telnet 方式即可)

服务的代码:

package javaBase.bio;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

public class BIOServer {

 

public static void main(String[] args) throws IOException {

// 创建线程池

 

ExecutorService ThreadPool = Executors.newCachedThreadPool();

 

// 创建 ServerSocket

ServerSocket serverSocket = new ServerSocket(6666);

while(true) {

System.out.println("线程信息 id ="+Thread.currentThread().getId()+" 名字:"+Thread.currentThread().getName());

System.out.println("等待连接.....");

//serverSocket.accept(): 侦听与此套接字建立的连接并接受它。 该方法将阻塞,直到建立连接为止。

final Socket socket = serverSocket.accept();

System.out.println("连接到一个客户端");

 

ThreadPool.execute(new Runnable() {

 

public void run() {

// 可以和客户端通讯

handler(socket);

 

}

});

}

}

 

// 编写一个handler方法,和客户端通讯

 public static void handler(Socket socket)  {

 System.out.println("线程信息 id ="+Thread.currentThread().getId()+" 名字:"+Thread.currentThread().getName());

 byte[] bytes = new byte[1024];

 // 通过 socket 获取输入流

 BufferedReader in = null;

 

 PrintWriter out = null;

 try {

 InputStream inputStream = socket.getInputStream();

// 循环的读取客户端发送的数据

 while(true) {

 System.out.println("线程信息 id ="+Thread.currentThread().getId()+" 名字:"+Thread.currentThread().getName());

 System.out.println("read...");

 in = new BufferedReader(new InputStreamReader(inputStream));

 // 输出客户端发送的数据

 System.out.println(in.readLine());

 out = new PrintWriter(socket.getOutputStream(),true);

 // 应答客户端

 out.println("aaa");

 }

} catch (Exception e) {

e.printStackTrace();

}finally {

System.out.println("关闭和client的连接");

try {

socket.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

 }

}

客户端代码:

package javaBase.bio;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class BIOClient {

 

public static void main(String[] args) throws UnknownHostException, IOException {

while(true) { // while 模拟多客户连接

Socket client = new Socket("192.168.1.102",6666);

 

PrintWriter out =null;

// 发送给服务器的信息

out = new PrintWriter(client.getOutputStream(),true);

out.println("bbb");

 

BufferedReader in =new BufferedReader(new InputStreamReader( client.getInputStream()));

 //输出接收服务器发送的信息

String serverStr = in.readLine();

System.out.println(serverStr);

}

 

}

 

}

四、Java BIO 问题分析

1每个请求都需要创建独立的线程,与对应的客户端进行数据 Read,业务处理,数据 Write

 

2当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。

 

3连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费