netty系列3-Java BIO编程
来源:互联网 发布:excel数据抽样 编辑:程序博客网 时间:2024/06/06 20:30
1. BIO特点
网络模型基本的模型是client/server模型,client进程和server进行通信,server端做绑定IP,并绑定端口;client端向服务端监听的地址发起连接请求,通过三次握手建立连接。如果建立成功,双方就可以通过socket进行通信。
Java中的BIO开发流程:
- server:ServerSocket负责绑定ip,启动监听端口
- client:Socket负责发起连接操作
- 连接建立成功之后,双方通过输入和输出流进行通信
2. Java BIO通信模型
2.1 server端主要流程
{ /* 1. 开启监听端口 */ ServerSocket server = new ServerSocket(8080); while (true) { /* 2. 监听客户端连接 */ Socket socket = server.accept(); /* 3. 创建线程处理客户端连接 */ new Thread(new TimeServerHandler(socket)).start(); }}
服务端监听客户端连接,每接收到一个连接,就创建一个业务线程来处理具体的请求,然后服务端继续监听客户端连接。
2.2 服务端TimeServerHandler主要逻辑
{ /* 0. socket是来自于服务端接收到的连接 */ /* 1. 构造input和output,分别用于从client读取和发送数据 */ BufferReader in = new BufferReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); /* 2. 读取请求内容 */ String body = in.readLine(); /* 3. 发送响应 */ out.println(System.currentTimeMillis()); /* 4. 释放资源 */ out.close(); in.close(); socket.close();}
服务端接收到的连接,业务线程TimeServerHandler主要负责从连接中读取客户端请求,并根据请求发送响应,处理完成请求之后,释放相关的资源。
2.3 client端主要流程:
{ /* 1. 向服务端发起创建连接申请 */ Socket socket = new Socket("127.0.0.1", 8080); /* 2. 构造inputStream,用于从server端读取数据 */ BufferReader in = new BufferReader(new InputStreamReader(socket.getInputStream())); /* 3. 构造outputStream,用于向server端发起请求 */ PrintWriter out = new PrintWriter(socket.getOutputStream(), true); /* 4. 发送请求 */ out.println("QUERY TIME ORDER"); /* 5. 获取相应内容并输出 */ System.out.println("response: " + in.readLine()); /* 6. 释放资源 */ out.close(); in.close(); socket.close();}
客户端主要向服务端发起创建连接申请,并在创建连接之后,发送请求,并接收响应。
3. BIO模型的问题
虽然服务端、客户端编程简单,很容易理解,但是存在一个比较严重的问题是每当有一个新的客户端请求接入时,服务端必须创建一个线程处理新接入的客户端链路,一个线程只能处理一个客户端连接。
在高性能服务器应用领域,往往需要处理成千上万个客户端的并发连接,这种模型显然不能满足高性能、高并发接入的场景。
后面我们会介绍通过线程池或者消息队列实现一个或者多个线程处理N个客户端的伪异步IO模型
4. 源代码
4.1 TimeServer.java
server端监听客户端连接代码:
package com.netease.netty.bio;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class TimeServer { public static void main(String []args) throws IOException { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // ... } } ServerSocket server = null; try { server = new ServerSocket(port); System.out.println("timeserver start in port: " + port); Socket socket = null; while (true) { socket = server.accept(); new Thread(new TimeServerHandler(socket)).start(); } } finally { if (server != null) { System.out.println("timeserver close"); server.close(); server = null; } } }}
4.2 TimeServerHandler.java
server端业务代码:
package com.netease.netty.bio;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class TimeServerHandler implements Runnable { private Socket socket; public TimeServerHandler(Socket socket) { this.socket = socket; } @Override 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 currentTime = null; String body = null; while (true) { body = in.readLine(); if (body == null) break; System.out.println("The time server receive order : " + body); currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date(System.currentTimeMillis()).toString() : "BAD ORDER!"; out.print(currentTime); } } catch (Exception e) { Utils.releaseAllSource(in, out, this.socket); in = null; out = null; this.socket = null; } }}
4.3 TimeClient.java
package com.netease.netty.bio;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class TimeClient { public static void main(String []args) { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { /* use default port number. */ } } 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.print("QUERY TIME ORDER"); System.out.println("Send order 2 server succeed"); String resp = in.readLine(); System.out.println("Now is : " + resp); } catch (Exception e) { //... } finally { Utils.releaseAllSource(in, out, socket); in = null; out = null; socket = null; } }}
4.4 Utils.java
工具类,主要释放连接相关的资源:
package com.netease.netty.bio;import java.io.BufferedReader;import java.io.IOException;import java.io.PrintWriter;import java.net.Socket;public class Utils { public static void releaseAllSource(BufferedReader in, PrintWriter out, Socket socket) { if (in != null) { try { in.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (out != null) { out.close(); } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }}
5. ref
- Netty权威指南
阅读全文
0 0
- netty系列3-Java BIO编程
- 《netty权威指南》2.1传统的BIO编程
- netty学习(二)--传统的bio编程
- Netty框架(一)————BIO编程
- java网络编程-tomcat Bio
- Netty系列之Netty并发编程分析
- Openssl之BIO系列(3)
- NIO,BIO,AIO,JAVA通讯编程学习笔记3
- Netty 网络IO BIO
- Netty入门--BIO
- BIO编程
- java 网络编程(二)TCPIP+BIO
- java网络编程(二)----同步阻塞bio
- Java网络编程之BIO(Socket)-yellowcong
- BIO、NIO、AIO的区别——Netty系列(一)
- BIO、NIO、AIO的区别——Netty系列(一)
- COPY Netty系列之Netty并发编程分析
- 1、传统BIO编程示例及缺点分析(netty-学习笔记)
- vue 三级控制
- eclipse无法编辑类报错:Unhandled event loop exception No more handles
- C语言:__asm关键字
- 判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如:给定s1 = AABCD和s2 = BCDAA,返回1,给定s1=abcd和s2=ACBD,返回0.
- 题目:JavaScript编程题 查找字符串"sdddrtkjsfkkkasjdddj"中出现次数最多的字符和次数。
- netty系列3-Java BIO编程
- 神经网络中的各种激活函数
- JDK各个版本的新特性jdk1.5-jdk8
- android中setImageResource加载大图片出现oom解决方案
- bootstrap使用教程
- leetcode 263|264|313. Ugly Number 1|2 313. Super Ugly Number
- Spring @Transactional注解不回滚不起作用无效
- com.google.protobuf学习笔记
- 部署模型-电商网站后台分布式部署方案