传统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. Python学习记录一

    1.这个在unix类的操作系统才有意义.#!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器:#!/usr/bin/env python这种用 ...

  2. android 拓展ImageView播放GIF动画

    原生Android控件ImageView并不能支持播放GiF格式的图片.如果将一张GIF的图片放入ImageView中,它只会显示图片的第一帧,不会产生任何动画效果. Android中播放GIF动画实 ...

  3. Python中的单元测试模块Unittest快速入门

    前言 为什么需要单元测试? 如果没有单元测试,我们会遇到这种情况:已有的健康运行的代码在经过改动之后,我们无法得知改动之后是否引入了Bug.如果有单元测试的话,只要单元测试全部通过,我们就可以保证没有 ...

  4. ESXI6.0 时间(时区)显示不一致

    ESXI6.0 时间(时区)显示不一致 来源 http://blog.51cto.com/jdonghong/1957118 近日由于设置ESXI计划任务,无意间发现了esxi服务器客服端时间和系统显 ...

  5. [洛谷P3701]「伪模板」主席树

    题目大意:太暴力了,就不写了,看这儿 题解:对于每个$byx$的人,从源点向人连边,容量为此人的寿命. 对于每个手气君的人,从人向汇点连边,容量为此人的寿命. 对于每个$byx$的人与手气君的人,如果 ...

  6. cf 834 E. Ever-Hungry Krakozyabra

    cf 834 E. Ever-Hungry Krakozyabra(爆搜+数位dp) 题意: 定义一种inedible tail为一个数把每一位数字按不降的顺序排列后,去掉前导0组成的序列 比如570 ...

  7. busybox根文件系统使用记录

    1.DHCP功能配置 1.1.配置Linux内核使能DHCP相关选项: [*]Networking support --> Networking support Networking optio ...

  8. Java代码实现真分页

    在JavaWeb项目中,分页是一个非常常见且重要的一个小方面.本次作为记载和学习,记录项目中出现的分页并做好学习记录.在这里,用的是SSH框架.框架可以理解如下图: 在JSP页面,描写的代码如下: & ...

  9. UIImage 获取url图片资源

    //UIImage 获取url图片资源 -(UIImage *) getImageFromURL:(NSString *)fileURL { UIImage * result; NSData * da ...

  10. hdu1024 Max Sum Plus Plus的另一种解法

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1024 http://www.51nod.com/onlineJudge/questionCode.htm ...