Netty 01 | 簡介與helloworld

傳統的Socket IO 比較

IO

NIO

傳送IO特點

  • 阻塞點
    server.accept();
    inputStream.read(bytes);

  • 單線程情況下只能有一個客戶端
    用線程池可以有多個客戶端連接,但是非常消耗性能

NIO的特點

ServerSocketChannel ServerSocket

SocketChannel Socket

Selector

SelectionKey

NIO的一些疑問

  1. 客戶端關閉的時候會拋出異常,死循環
    解決方案
	int read = channel.read(buffer);
		if(read > 0){
			byte[] data = buffer.array();
			String msg = new String(data).trim();
			System.out.println("服務端收到信息:" + msg);
			
			//回寫數據
			ByteBuffer outBuffer = ByteBuffer.wrap("好的".getBytes());
			channel.write(outBuffer);// 將消息回送給客戶端
		}else{
			System.out.println("客戶端關閉");
			key.cancel();
		}

  1. selector.select();阻塞,那爲什麼說nio是非阻塞的IO?

    selector.select()
    selector.select(1000);不阻塞
    selector.wakeup();也可以喚醒selector
    selector.selectNow();也可以立馬返還

  2. SelectionKey.OP_WRITE是代表什麼意思
    OP_WRITE表示底層緩衝區是否有空間,是則響應返還true

netty可以運用在那些領域?

  1. 分佈式進程通信
    例如: hadoop、dubbo、akka等具有分佈式功能的框架,底層RPC通信都是基於netty實現的,這些框架使用的版本通常都還在用netty3.x
  2. CS IM通信
  3. 遊戲服務器開發
    最新的遊戲服務器有部分公司可能已經開始採用netty4.x 或 netty5.x

1、netty服務端hello world案例

SimpleChannelHandler 處理消息接收和寫
{
  messageReceived接收消息

  channelConnected新連接,通常用來檢測IP是否是黑名單

  channelDisconnected鏈接關閉,可以再用戶斷線的時候清楚用戶的緩存數據等
}
package com.server;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
/**
 * netty服務端入門
 *
 */
public class Server {

	public static void main(String[] args) {

		//服務類
		ServerBootstrap bootstrap = new ServerBootstrap();
		
		//boss線程監聽端口,worker線程負責數據讀寫
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();
		
		//設置niosocket工廠
		bootstrap.setFactory(new NioServerSocketChannelFactory(boss, worker));
		
		//設置管道的工廠
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			
			@Override
			public ChannelPipeline getPipeline() throws Exception {

				ChannelPipeline pipeline = Channels.pipeline();
				pipeline.addLast("decoder", new StringDecoder());//上游
				pipeline.addLast("encoder", new StringEncoder());//下游
				pipeline.addLast("helloHandler", new HelloHandler());
				return pipeline;
			}
		});
		
		bootstrap.bind(new InetSocketAddress(10101));
		
		System.out.println("start!!!");
		
	}

}

2、netty客戶端hello world案例

channelDisconnected與channelClosed的區別?

channelDisconnected只有在連接建立後斷開纔會調用
channelClosed無論連接是否成功都會調用關閉資源

package com.client;

import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
/**
 * netty客戶端入門
 *
 */
public class Client {

	public static void main(String[] args) {
		
		//服務類
		ClientBootstrap bootstrap = new  ClientBootstrap();
		
		//線程池
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();
		
		//socket工廠
		bootstrap.setFactory(new NioClientSocketChannelFactory(boss, worker));
		
		//管道工廠
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				ChannelPipeline pipeline = Channels.pipeline();
				pipeline.addLast("decoder", new StringDecoder());
				pipeline.addLast("encoder", new StringEncoder());
				pipeline.addLast("hiHandler", new HiHandler());//
				return pipeline;
			}
		});
		
		//連接服務端
		ChannelFuture connect = bootstrap.connect(new InetSocketAddress("127.0.0.1", 10101));
		Channel channel = connect.getChannel();//與 HiHandler 是統一個Channel,在這裏與Hihandler 中處理一樣
		
		System.out.println("client start");
		
		Scanner scanner = new Scanner(System.in);
		while(true){
			System.out.println("請輸入");
			channel.write(scanner.next());
		}
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章