網路程式設計(BIO、NIO、Netty )
【傳統BIO通訊模型圖】
同步阻塞式I/O建立的Client原始碼:package com.cherry.socket.bio; import java.io.*; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author
[email protected] * @create 2018/4/13 9:24 * @desc **/ public class BIOServerBootStrap { public static void main(String[] args) throws IOException { //1.Create ServerSocket ServerSocket serverSocket = new ServerSocket(); //2.Set up the service listener port serverSocket.bind(new InetSocketAddress(9999)); //Create a thread pool ExecutorService threadPool = Executors.newFixedThreadPool(150); while (true){ //3.Waitting for request System.out.println("----waitting for request----"); final Socket socket = serverSocket.accept(); threadPool.submit(new Runnable() { public void run() { try { //4.Obtain user intent InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); String line = null; while ((line=br.readLine())!=null){ sb.append(line); } System.out.println("----the message get by server---- : "+sb); //5.client response OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); pw.println("server time"+new Date().toLocaleString()); pw.flush(); socket.shutdownOutput();//Tell the client to write the cut-off //6.release the resource socket.close(); } catch (IOException e) { e.printStackTrace(); } } }); } } }
package com.cherry.socket.bio;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
* @author [email protected]
* @create 2018/4/13 11:07
* @desc
**/
public class BIOClientBootStrap {
public static void main(String[] args) throws IOException {
//1.Create client socket
Socket socket = new Socket();
//2.connect to the server
socket.connect(new InetSocketAddress("127.0.0.1",9999));
//3.makes requests to the server
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("Hello,This is Client 2");
pw.flush();
socket.shutdownOutput();//Tell the Server to write the cut-off
//4.get the response
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line =null;
while ((line=br.readLine())!=null){
sb.append(line);
}
System.out.println("----The message get by client---- : "+sb);
//5.release the resource
socket.close();
}
}
NIOnon-blocking IO, NIO提供了與傳統BIO模型中的Socket和ServerSocket相對應的SocketChannel和ServerSocketChannel兩種不同的套接字通道實現。新增的著兩種通道都支援阻塞和非阻塞兩種模式。阻塞模式使用就像傳統中的支援一樣,比較簡單,但是效能和可靠性都不好;非阻塞模式正好與之相反。對於低負載、低併發的應用程式,可以使用同步阻塞I/O來提升開發速率和更好的維護性;對於高負載、高併發的(網路)應用,應使用NIO的非阻塞模式來開發。NIO程式設計是面向通道的(BIO是面向流的),流分為寫入/寫出,是單向的,意味著通道是可以進行雙向讀寫的。NIO所有基於channel的API對資料的操作都是間接通過操作緩衝區ByteBufferIn : 磁碟 --通道--> ByteBuffer(記憶體)-->資料(記憶體)Out: 資料(記憶體)-->ByteBuffer(記憶體) --> 通道 --> 磁碟 NIO程式設計涉及ServerSocketChannel、SocketChannel、ByteBuffer、Selector(通道選擇器)服務端原始碼:
package com.cherry.socket.nio;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
* @author [email protected]
* @create 2018/4/13 11:34
* @desc
**/
public class NIOServerBootStrap {
public static void main(String[] args) throws IOException {
//1.Create ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
//2.Set up the service listener port
ssc.socket().bind(new InetSocketAddress(9999));
//3.Set up the channel to be non-blocking
ssc.configureBlocking(false);
//4.Create channel selector
Selector selector =Selector.open();
//5.註冊事件型別
ssc.register(selector, SelectionKey.OP_ACCEPT);
//6.遍歷事件處理列表
while (true){
int num = selector.select();
if (num>0){
//獲取所有待處理的keys
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()){
SelectionKey key = keys.next();
//處理事件
if(key.isAcceptable()){
System.out.println("----key isAcceptable----");
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = channel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_ACCEPT);
}else if (key.isReadable()){
System.out.println("----key isReadable(read)----");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true){
buffer.clear();
int n = channel.read(buffer);
if (n==1)break;
baos.write(buffer.array(),0,n);
}
channel.register(selector,SelectionKey.OP_WRITE,baos);
} else if (key.isWritable()){
System.out.println("----key isWritable(write)----");
SocketChannel channel = (SocketChannel) key.channel();
ByteArrayOutputStream baos = (ByteArrayOutputStream) key.attachment();
baos.write("_伺服器追加".getBytes());
ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray());
channel.write(buffer);
channel.socket().shutdownOutput();
channel.close();
}
//移除時間列表
keys.remove();
}
} else {
continue;
}
}
}
}
NettyNetty的通訊管道:通過AOP的程式設計思想(責任鏈設計模式),實現訊息的編解碼。服務端程式設計:1)建立ServerBootstrap sbt=new ServerBootstrap();2)建立EventLoopGroup boss、worker3)關聯boss和worker> sbt.group(boss,worker);4)設定ServerSocketChannel實現類sbt.channel(NioServerSocketChannel);5)初始化通道sbt.childHandler(初始化通道);6)繫結埠並啟動服務ChannelFuture future=sbt.bind(port).sync();7)等待服務關閉 future.channel().closeFuture().sync();8) 釋放執行緒資源boss、worker # shutdownGraceFully();服務端原始碼:package com.cherry.socket.netty.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @author [email protected]
* @create 2018/4/16 9:51
* @desc
**/
public class ServerBootStrap {
public static void main(String[] args) throws InterruptedException {
//1.Create ServerBootstrap
ServerBootstrap sbt = new ServerBootstrap();
//2.Create thread pool(boss & worker)
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
//3.關聯執行緒池(boss負責請求轉發,worker負責事件處理)
sbt.group(boss,worker);
//4.Set up the server
sbt.channel(NioServerSocketChannel.class);
//5.Initialize the communication channel (key point)
sbt.childHandler(new ServerChannelInitizlizer());
//6.Bind listening port
System.out.println("我在@9999埠監聽...");
ChannelFuture channelFuture = sbt.bind(9999).sync();
//7.Wait for the server to close
channelFuture.channel().closeFuture().sync();
//l
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
package com.cherry.socket.netty.server;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
/**
* @author [email protected]
* @create 2018/4/16 10:26
* @desc
**/
public class ServerChannelHander extends ChannelHandlerAdapter {
/*捕獲資料在通道傳輸過程中的異常*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println("錯誤:"+cause.getMessage());
}
/*接收資料,並響應*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ChannelFuture channelFuture = ctx.writeAndFlush(msg);
//關閉通道
channelFuture.addListener(ChannelFutureListener.CLOSE);
}
}
package com.cherry.socket.netty.server;
import com.cherry.socket.netty.server.ServerChannelHander;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
/**
* @author [email protected]
* @create 2018/4/16 10:02
* @desc
**/
public class ServerChannelInitizlizer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//communication channel
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ServerChannelHander());
}
}
客戶端程式設計:1)建立Bootstrap sbt=new Bootstrap();2)建立EventLoopGroup worker3)關聯boss和worker> sbt.group(worker);4)設定SocketChannel實現類sbt.channel(NioSocketChannel);5)初始化通道sbt.handler(初始化通道);6)繫結埠並啟動服務ChannelFuture future=sbt.connect(host,port).sync();7)等待服務關閉 future.channel().closeFuture().sync();8)釋放執行緒資源worker # shutdownGraceFully();客戶端原始碼:package com.cherry.socket.netty.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* @author [email protected]
* @create 2018/4/16 11:15
* @desc
**/
public class ClientBootStrap {
public static void main(String[] args) throws InterruptedException {
//1.Create Bootstrap
Bootstrap bt = new Bootstrap();
//2.Create thread pool(worker)
EventLoopGroup worker = new NioEventLoopGroup();
//3.關聯執行緒池
bt.group(worker);
//4.Set up the client
bt.channel(NioSocketChannel.class);
//5.Initialize the communication channel (key point)
bt.handler(new ClientChannelInitializer());
//6.連線
ChannelFuture channelFuture = bt.connect("127.0.0.1",9999).sync();
//7.Wait for the server to close
channelFuture.channel().closeFuture().sync();
//8.release the resource
worker.shutdownGracefully();
}
}
package com.cherry.socket.netty.client;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import javax.xml.transform.Source;
/**
* @author [email protected]
* @create 2018/4/16 11:22
* @desc
**/
public class ClientChannelHander extends ChannelHandlerAdapter {
/*捕獲資料在通道傳輸過程的異常*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//super.exceptionCaught(ctx, cause);
System.out.println("錯誤:"+cause.getMessage());
}
/*接收資料*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//super.channelRead(ctx, msg);
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println(((ByteBuf)msg).toString(CharsetUtil.UTF_8));
}
/*連結伺服器時傳送資料*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//super.channelActive(ctx);
ByteBuf buf = Unpooled.buffer();
buf.writeBytes("你好,我是客戶端!".getBytes());
ctx.writeAndFlush(buf);
}
}
package com.cherry.socket.netty.client;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
/**
* @author [email protected]
* @create 2018/4/16 11:20
* @desc
**/
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//communication channel
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ClientChannelHander());
}
}
上述BIO NIO Netty所用的pom.xml<!-- socket 相關 注意版本,不然有些方法不能用-->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
通過對Netty的分析,我們將他的優點總結如下:1.API使用簡單,開發門檻低;2.功能強大,預設了很多編碼功能,支援多種主流協議;3.定製能力強,可以通過ChannelHandler對通訊框架進行靈活擴充套件;4.效能高,通過與其他的主流NIO框架對比,Netty的綜合性能最優;5.成熟,穩定,Netty修復了已經發現的所有JDK NIO BUG,業務開發人員不需要再為NIO的BUG煩惱;6.社群活躍,版本迭代週期短;7.經過大規模的商業應用考驗,質量得到驗證。Netty在網際網路、大資料、網路遊戲、企業應用、電信軟體等眾多領域已經得到了成功商用,也 證明他已經完全能滿足不同行業的商應用了;基於上述這些,我將在下一篇文章中寫一些關於如何實現高效能可擴充套件RPC,希望對大家有所幫助!相關推薦
網路程式設計(BIO、NIO、Netty )
簡介:BIO:同步阻塞式IO,伺服器實現模式為一個連線一個執行緒,即客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要的執行緒開銷,當然可以通過執行緒池機制改善。 NIO:同步非阻塞式IO,伺服器實現模式為一個請求一個執行緒,即客戶端
基於TCP的socket套接字的網路程式設計(客戶端/服務端模式)
於資料完整性要求較高的場合,就應採用TCP協議。 IP網路層提供IP定址和路由。因為在網路上資料可以經由多條線路到達目的地,網路層負責找出最佳的傳輸線路。 IP地址與資料包: IP層就是把資料分組從一個主機跨越千山萬水搬運到另外一主機, 並且這搬運服務一點都不可靠, 丟包、
網路程式設計——(connectTCP和connectUDP的實現)2.利用TCP/UDP完成檔案傳輸的設計和實現(下)
每個客戶與伺服器建立聯絡必須: 選擇協議(UDP或TCP) 查詢伺服器的機器名 查詢所期望的服務並將其對映到協議埠號 分配套接字並與之連線 將這部分工作進行封裝,置於某個過程當中,只需一次編碼。 我們想要實現以下抽象: socket = connectTCP(mac
基於訊息實現系統間的通訊(BIO,NIO,AIO)學習。
當系統之間要通訊時,就向外傳送訊息,訊息可以是位元組流,位元組陣列,甚至是java物件,其他系統接受訊息後,則進行相應的業務處理。 訊息方式的系統間通訊,通常基於網路協議來實現,常用的實現系統間的通訊協議有:TCP/IP 和UDP/IP。 TCP/IP是一種可靠的網路資料
系統之間通訊方式(BIO和NIO的區別)(二)
4-3、NIO通訊框架 目前流行的NIO框架非常的多。在論壇上、網際網路上大家討論和使用最多的有以下幾種: 原生JAVA NIO框架: JAVA NIO通訊框架基於多路複用IO原理,我們將詳細講解它的工作原理。 APACHE MINA 2: 是一個網路應用程
Java 網路IO程式設計總結(BIO、NIO、AIO均含完整例項程式碼)
第一段內容轉載自:http://blog.51cto.com/stevex/1284437 先來個例子理解一下概念,以銀行取款為例: 同步 : 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫)。 非同步
Java IO 程式設計(BIO、NIO、AIO完整例項程式碼)
本文會從傳統的BIO到NIO再到AIO自淺至深介紹,並附上程式碼講解。 原始碼地址: https://github.com/kkman2008/java-IO.git 下面程式碼中會使用這樣一個
BIO、NIO、AIO及網路程式設計
一. 網路程式設計的一些基礎 1.先說明一下執行緒的掛起、阻塞、睡眠 執行緒從建立、執行到結束總是處於下面五個狀態之一:新建狀態、就緒狀態、執行狀 &nb
Java基礎:java網路程式設計IO總結(BIO、NIO、AIO)
1.基本概念 在Java網路通訊中,最基本的概念就是Socket程式設計了。Socket又稱“套接字” 向網路發出請求或者應答網路請求。 Socket 和ServerSocket類庫位於 Java.net 包中。ServerSocket用於伺服器端,Socket是建立網路連線時使用的
網路程式設計之BIO、NIO、AIO
TCP直連Socket與ServerSocket通訊 Server.java import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class S
java架構之路-(netty專題)初步認識BIO、NIO、AIO
本次我們主要來說一下我們的IO阻塞模型,只是不多,但是一定要理解,對於後面理解netty很重要的 IO模型精講 IO模型就是說用什麼樣的通道進行資料的傳送和接收,Java共支援3種網路程式設計IO模式:BIO,NIO,AIO。 BIO BIO(Blocking IO) 同步阻塞模型,一
網路程式設計(InetAddress類、Socket和ServerSocket、實現客戶端和伺服器之間的雙向通訊)
網路程式設計的底層是IO,通過IO將一臺計算機中的資料傳送到另一臺計算機中。傳送的時候,要知道接受方的地址,該地址即為IP地址。知道IP地址後即可進行傳送。A向B發訊息,訊息是發過去了,但是B要怎樣接受呢?因此定義了埠,B監聽了A所使用的埠。A發的訊息中含有埠號,當B接受到訊息時,知道了埠號
Java核心(五)深入理解BIO、NIO、AIO
導讀:本文你將獲取到:同/非同步 + 阻/非阻塞的效能區別;BIO、NIO、AIO 的區別;理解和實現 NIO 操作 Socket 時的多路複用;同時掌握 IO 最底層最核心的操作技巧。 BIO、NIO、AIO 的區別是什麼? 同/非同步、阻/非阻塞的區別是什麼? 檔案讀寫最優雅的實現方式是什
Linux IO模式(BIO、NIO、IO多路複用、非同步IO)及 select、poll、epoll詳解
同步IO和非同步IO,阻塞IO和非阻塞IO分別是什麼,到底有什麼區別?不同的人在不同的上下文下給出的答案是不同的。所以先限定一下本文的上下文。 本文討論的背景是Linux環境下的network IO。 一 概念說明 在進行解釋之前,首先要說明幾個概念: -
javaSE (四十)網路程式設計(TCP傳輸、伺服器多執行緒、網路程式設計練習:反轉字串、上傳檔案)
1、TCP傳輸: 1.客戶端 建立Socket連結服務端(指定ip地址,埠號),通過ip地址找到對應的伺服器 呼叫Socket的getInputStream和getOutputStream方法獲取和伺服器端相連的IO流 2.伺服器端 建立Se
javaSE (三十九)網路程式設計(網路程式設計三要素和Socket、UDP傳輸、多執行緒UDP傳輸)
1、網路程式設計三要素: 地址:定位電腦 本地迴路地址:127.0.0.1 廣播地址:255.255.255.255 埠號:定位電腦中的程式 o~65525 儘量使用1024以上的 協議:資料交換的規則/標準 UDP: 面向無連線,資料不安全,速度快,不區分客戶端與服
Java中網路IO的實現方式-BIO、NIO、AIO
在網路程式設計中,接觸到最多的就是利用Socket進行網路通訊開發。在Java中主要是以下三種實現方式BIO、NIO、AIO。 關於這三個概念的辨析以前一直都是好像懂,但是表達的不是很清楚,下面做個總結完全辨析清楚。 1. BIO方式
JAVA網路IO(BIO、NIO、AIO)
例子一: “阻塞”與"非阻塞"和"同步"與“非同步"不能簡單的從字面理解,提供一個從分散式系統角度的回答。1.同步與非同步同步和非同步關注的是訊息通訊機制 (synchronous communic
學習Netty前對BIO、NIO、AIO的理解
概念 Netty是一個提供了易於使用的API的客戶端/伺服器框架 高併發NIO(非阻塞IO) 傳輸快,零拷貝(在Java中,記憶體分為堆疊常量池等。假設現在我們有一些資料,我們需要從IO裡面讀取並且放到堆裡面,那麼一般都會從IO流將資料讀入緩衝區,然後再從緩衝區裡
Java中的BIO、NIO、AIO(NIO2)
搞清楚了以上概念以後,我們再回過頭來看看,Reactor模式和Proactor模式。 (其實阻塞與非阻塞都可以理解為同步範疇下才有的概念,對於非同步,就不會再去分阻塞非阻塞。對於使用者程序,接到非同步通知後,就直接操作程序使用者態空間裡的資料好了。) 首先來看看Reactor模式,Reac