Java网络通信基础系列-BIO模型
关于Java网络通讯方面的内容,下载地址:https://github.com/mldn/echo,我也做的Fork,地址:https://github.com/bijian1013/echo
Java基础知识:BIO、NIO、AIO三者的技术实现,以及彼此之间的区别
Netty:TCP 程序实现为主,代码的核心:Echo程序模型,通过网络实现一个基础的Echo。
一.BIO模型:同步阻塞IO处理
在程序的开发之中Java里面最小的处理单元就是线程,也就是说每一个线程可以进行IO的处理,在处理之中,该线程无法进行任何的其他操作。
多线程是不可能无限制进行创造的,所以需要去考虑堆线程进行有效的个数控制。
如果产生的线程过多,那么直接的问题在于,处理性能降低 ,响应的速度变慢。 需要去区分操作系统的内核线程以及用户线程的区别,所以最好与内核线程有直接联系,需要使用到固定线程池。
【BIO】现在烧水,意味着你现在需要一直盯着水壶去看,一直看它已经烧为止,在这之中你什么都干不了。

二.实例
1.项目结构

echo-util:公共的工具工程
echo-base:基于java开发的bio、nio、aio实例
echo-netty:基于netty开发的网络通信实例
echo-http:基于netty开发的http服务实例
2.实例代码
echo-util工程中的代码:
HostInfo.java
package com.bijian.info; public interface HostInfo { public static final String HOST_NAME = "localhost" ; public static final int PORT = 9999 ; public static final String SEPARATOR = "%$%" ; }
InputUtil.java
package com.bijian.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class InputUtil { private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); private InputUtil() { } /** * 实现键盘数据的输入操作 ,可以返回的数据类型为String * * @param prompt 提示信息 * @return 输入的数据返回 */ public static String getString(String prompt) { boolean flag = true; // 数据接收标记 String str = null; while (flag) { System.out.print(prompt); try { str = KEYBOARD_INPUT.readLine(); // 读取一行数据 if (str == null || "".equals(str)) { System.out.println("数据输入错误 ,该内容不允许为空:"); } else { flag = false; } } catch (IOException e) { System.out.println("数据输入错误 ,该内容不允许为空:"); } } return str; } }
BIO实例代码:
BIOEchoServer.java
package com.bijian.bio.server; import com.bijian.info.HostInfo; import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class BIOEchoServer { public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(HostInfo.PORT) ;// 设置监听端口 System.out.println("服务器端已经启动,监听的端口为:" + HostInfo.PORT); boolean flag = true ; ExecutorService executorService = Executors.newFixedThreadPool(10) ; while(flag) { Socket client = serverSocket.accept() ; executorService.submit(new EchoClientHandler(client)) ; } executorService.shutdown() ; serverSocket.close() ; } private static class EchoClientHandler implements Runnable { private Socket client ; // 每一个客户端都需要启动一个任务(task)来执行。 private Scanner scanner ; private PrintStream out ; private boolean flag = true ; // 循环标记 public EchoClientHandler(Socket client) { this.client = client ; // 保存每一个客户端操作 try { this.scanner = new Scanner(this.client.getInputStream()) ; this.scanner.useDelimiter("\n") ; // 设置换行符 this.out = new PrintStream(this.client.getOutputStream()) ; } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { while(this.flag) { if (this.scanner.hasNext()) { // 现在有数据进行输入 String val = this.scanner.next().trim() ; // 去掉多余的空格内容 System.err.println("{服务器端}" + val); if("byebye".equalsIgnoreCase(val)) { this.out.println("ByeByeByte..."); this.flag = false ; } else { out.println("【ECHO】" + val); } } } this.scanner.close(); this.out.close(); try { this.client.close(); } catch (IOException e) { } } } }
BIOEchoClient.java
package com.bijian.bio.client; import com.bijian.info.HostInfo; import com.bijian.util.InputUtil; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class BIOEchoClient { public static void main(String[] args) throws Exception { Socket client = new Socket(HostInfo.HOST_NAME,HostInfo.PORT) ; // 定义连接的主机信息 Scanner scan = new Scanner(client.getInputStream()) ; // 获取服务器端的响应数据 scan.useDelimiter("\n") ; PrintStream out = new PrintStream(client.getOutputStream()) ; // 向服务器端发送信息内容 boolean flag = true ; // 交互的标记 while(flag) { String inputData = InputUtil.getString("请输入要发送的内容:").trim() ; out.println(inputData); // 把数据发送到服务器端上 if(scan.hasNext()) { String str = scan.next().trim() ; System.out.println(str); } if ("byebye".equalsIgnoreCase(inputData)) { flag = false ; } } client.close(); } }
先运行BIOEchoServer.java,再运行BIOEchoClient.java,效果如下:

PS:其它知识
Java基本功:合理的类设计+多线程(JUC)+反射机制+网络通讯+数据结构+JVM
Shiro、SpringDataJPA、MyBatis、OAuth软件设计方法、Linux使用需要熟练(如果你可以独立的实现一套分布式的认证于授权管理,那么就证明你的水平不低了。
架构师经常需要精通几门语言。
docker+k8s+devops。
特别说明:这是开课吧的公开课
posted on 2019-06-15 11:37 bijian1013 阅读(574) 评论(0) 收藏 举报
浙公网安备 33010602011771号