传统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;
}
}
}
}

NIO入门之BIO的更多相关文章

  1. 第二章 NIO入门

    传统的同步阻塞式I/O编程 基于NIO的非阻塞编程 基于NIO2.0的异步非阻塞(AIO)编程 为什么要使用NIO编程 为什么选择Netty 第二章 NIO 入门 2.1 传统的BIO编程 2.1.1 ...

  2. Java NIO入门(二):缓冲区内部细节

    Java NIO 入门(二)缓冲区内部细节 概述 本文将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor). 状态变量是前一文中提到的"内部统计机制"的 ...

  3. Java NIO入门

    NIO入门 前段时间在公司里处理一些大的数据,并对其进行分词.提取关键字等.虽说任务基本完成了(效果也不是特别好),对于Java还没入门的我来说前前后后花了2周的时间,我自己也是醉了.当然也有涉及到机 ...

  4. NIO入门之轻松读取大文件

    NIO入门之轻松读取大文件 今天同事碰到了一个问题,从游戏服务器下载下来的输出log有一个多G大.用记事本打不开,EditPlus也打不开,都提示文件太大.用word也打不开,提示文件大于512M.打 ...

  5. NIO 入门(转)

    NIO 入门 Greg Travis2003 年 11 月 17 日发布 分享此页面 WeiboGoogle+用电子邮件发送本页面 20 在开始之前 关于本教程 新的输入/输出 (NIO) 库是在 J ...

  6. NIO入门-----01

    package com.sico.pck01_nio; import java.nio.ByteBuffer; import org.junit.Test; /**  * @author Sico   ...

  7. 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

    本文原题“<NIO 入门>,作者为“Gregory M. Travis”,他是<JDK 1.4 Tutorial>等书籍的作者. 1.引言 Java NIO是Java 1.4版 ...

  8. 从Socket入门到BIO,NIO,multiplexing,AIO

    Socket入门 最简单的Server端读取Client端内容的demo public class Server { public static void main(String [] args) t ...

  9. 从Socket入门到BIO,PIO,NIO,multiplexing,AIO(未完待续)

    Socket入门 最简单的Server端读取Client端内容的demo public class Server { public static void main(String [] args) t ...

随机推荐

  1. Opencv3.3.1安装包

    这个资源是Opencv3.3.1安装包,包括Windows软件包,Android软件包,IOS软件包,还有opencv的源代码:需要的下载吧. 点击下载

  2. 201621123034 《Java程序设计》第9周学习总结

    作业09-集合与泛型 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 答:Map的HashMap中使用嵌套类static class Node<K,V& ...

  3. 前端构建工具gulpjs的使用介绍及技巧 (转)

    gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...

  4. BZOJ 1731: [Usaco2005 dec]Layout 排队布局

    Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ ...

  5. BZOJ4894 天赋 【矩阵树定理】

    题目链接 BZOJ4894 题解 双倍经验P5297 题解 #include<iostream> #include<cstring> #include<cstdio> ...

  6. bestcoder15_love

    #include <iostream> #include <stdio.h> #include <string.h> #include <vector> ...

  7. 使用 redux 监听插件的使用

    首先需要在chrome浏览器当中下载redux插件 接着在你的项目当中加上**window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX ...

  8. 封装scroll()

    function scroll(){ if(window.pageYOffset !== undefined){ return { "top": window.pageYOffse ...

  9. BAT脚本编写教程入门提高篇

    BAT脚本编写教程入门提高篇 批处理文件的参数 批处理文件还可以像C语言的函数一样使用参数(相当于DOS命令的命令行参数),这需要用到一个参数表示符“%”. %[1-9]表示参数,参数是指在运行批处理 ...

  10. Unicode字符集和多字节字符集关系

      在计算机中字符通常并不是保存为图像,每个字符都是使用一个编码来表示的,而每个字符究竟使用哪个编码代表,要取决于使用哪个字符集(charset). 在最初的时候,Internet上只有一种字符集—— ...