1. 程式人生 > >Netty實現長連線簡單例子

Netty實現長連線簡單例子

Netty實現長連線的簡單例子

服務端

NettyServerBootstrap提供長連線服務

public class NettyServerBootstrap {

	private static final Log log = LogFactory.getLog(NettyServerBootstrap.class);
	private Integer port;
	private SocketChannel socketChannel;
	public NettyServerBootstrap(Integer port) throws Exception {
		this.port = port;
		bind(port);
	}
	public Integer getPort() {
		return port;
	}
	public void setPort(Integer port) {
		this.port = port;
	}
	public SocketChannel getSocketChannel() {
		return socketChannel;
	}
	public void setSocketChannel(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
	}
	private void bind(int serverPort) throws Exception {
		// 連線處理group
		EventLoopGroup boss = new NioEventLoopGroup();
		// 事件處理group
		EventLoopGroup worker = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();
		// 繫結處理group
		bootstrap.group(boss, worker);
		bootstrap.channel(NioServerSocketChannel.class);
		// 保持連線數
		bootstrap.option(ChannelOption.SO_BACKLOG, 1024 * 1024);
		// 有資料立即傳送
		bootstrap.option(ChannelOption.TCP_NODELAY, true);
		// 保持連線
		bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
       // 處理新連線
		bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel sc) throws Exception {
				// 增加任務處理
				ChannelPipeline p = sc.pipeline();
				p.addLast(new MessageDecoder(), new MessageEncoder(), new NettyServerHandler());
			 }
		});

		ChannelFuture f = bootstrap.bind(serverPort).sync();
		if (f.isSuccess()) {
			log.info("long connection started success");
		} else {
			log.error("long connection started fail");
		}
	}
}

啟動服務,監聽9999

public static void main(String[] args) {
		try {
			new NettyServerBootstrap(9999);
		} catch (Exception e) {
			
			e.printStackTrace();
		}
}

定義客戶端服務端通訊協議,一下是一個簡單的通訊協議

協議分為headerbody兩部分,都是用網路位元組序(BIG ENDIAN

header{

magic 32bit;  //校驗用固定值0x0CAFFEE0

version 8bit;  //版本號

type 8bit;     //型別,請求或者響應

seq 32bit;     //序號標記一對請求響應

length 32bit;  //body長度

}

body{

}

根據通訊協議,編寫解碼器和編碼器

解碼器MessageDecoder

public class MessageDecoder extends ByteToMessageDecoder {
	private static final int MAGIC_NUMBER = 0x0CAFFEE0;
	public MessageDecoder() {

	}
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		if (in.readableBytes() < 14) {
			return;
		}
		// 標記開始讀取位置
		in.markReaderIndex();

		int magic_number = in.readInt();

		if (MAGIC_NUMBER != magic_number) {
			ctx.close();
			return;
		}

		@SuppressWarnings("unused")
		byte version = in.readByte();

		byte type = in.readByte();
		int squence = in.readInt();
		int length = in.readInt();

		if (length < 0) {
			ctx.close();
			return;
		}

		if (in.readableBytes() < length) {
			// 重置到開始讀取位置
			in.resetReaderIndex();
			return;
		}

		byte[] body = new byte[length];
		in.readBytes(body);

		RequestInfoVO req = new RequestInfoVO();
		req.setBody(new String(body, "utf-8"));
		req.setType(type);
		req.setSequence(squence);
		out.add(req);
	}
}

編碼器MessageEncoder

public class MessageEncoder extends MessageToByteEncoder<RequestInfoVO> {

	private static final String DEFAULT_ENCODE = "utf-8";

	private static final int MAGIC_NUMBER = 0x0CAFFEE0;

	public MessageEncoder() {
	}

	@Override
	protected void encode(ChannelHandlerContext ctx, RequestInfoVO msg, ByteBuf out) throws Exception {

		@SuppressWarnings("resource")
		ByteBufOutputStream writer = new ByteBufOutputStream(out);
		byte[] body = null;

		if (null != msg && null != msg.getBody() && "" != msg.getBody()) {
			body = msg.getBody().getBytes(DEFAULT_ENCODE);
		}

		writer.writeInt(MAGIC_NUMBER);

		writer.writeByte(1);

		writer.writeByte(msg.getType());

		writer.writeInt(msg.getSequence());

		if (null == body || 0 == body.length) {
			writer.writeInt(0);
		} else {
			writer.writeInt(body.length);
			writer.write(body);
		}
	}

}

服務端事件處理NettyServerHandler

@Sharable
public class NettyServerHandler extends SimpleChannelInboundHandler<RequestInfoVO> {
	private static final Log log = LogFactory.getLog(NettyServerHandler.class);

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, RequestInfoVO msg) throws Exception {
		//
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		
	}


	@Override
	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
		
	}

}

客戶端

NettyClientBootstrap連線長連線服務

public class NettyClientBootstrap {
	private int port;
	private String host;
	private SocketChannel socketChannel;
	public NettyClientBootstrap(int port, String host) throws Exception {
		this.host = host;
		this.port = port;
		start();
	}
	private void start() throws Exception {
		EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
		Bootstrap bootstrap = new Bootstrap();
		bootstrap.channel(NioSocketChannel.class);
		bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
		bootstrap.option(ChannelOption.TCP_NODELAY, true);
		bootstrap.group(eventLoopGroup);
		bootstrap.remoteAddress(this.host, this.port);
		bootstrap.handler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel socketChannel) throws Exception {
				socketChannel.pipeline().addLast(new MessageDecoder(), new MessageEncoder(), new NettyClientHandler());
			}
		});
		ChannelFuture future = bootstrap.connect(this.host, this.port).sync();
		if (future.isSuccess()) {
			socketChannel = (SocketChannel) future.channel();
			System.out.println("connect server  success|");
		}
	}
	public int getPort() {
		return this.port;
	}
	public void setPort(int port) {
		this.port = port;
	}

	public SocketChannel getSocketChannel() {
		return socketChannel;
	}
	public void setSocketChannel(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
	}
	public String getHost() {
		return host;
	}
	public void setHost(String host) {
		this.host = host;
	}
}

初始化客戶端

public static void main(String[] args) throws Exception {
		NettyClientBootstrap bootstrap = new NettyClientBootstrap(9999, "127.0.0.1");
		int i = 1;

		while (true) {
			TimeUnit.SECONDS.sleep(2);
			RequestInfoVO req = new RequestInfoVO();
			req.setSequence(123456);
			req.setType((byte) 1);
			req.setSequence(0);
			req.setBody(String.valueOf((new Date()).getTime()));
			bootstrap.getSocketChannel().writeAndFlush(req);
			i++;
		}
	}

根據協議編寫編碼器,解碼器,同服務端編碼器、解碼器

客戶端事件處理

public class NettyClientHandler extends SimpleChannelInboundHandler<RequestInfoVO> {

	@Override
	protected void messageReceived(ChannelHandlerContext ctx, RequestInfoVO msg) throws Exception {
		System.out.println(msg.getBody());
		RequestInfoVO req = new RequestInfoVO();
		req.setSequence(msg.getSequence());
		req.setType(msg.getType());
		if (2 == msg.getType()) {
			req.setBody("client");
			ctx.channel().writeAndFlush(req);
		} else if (3 == msg.getType()) {
			req.setBody("zpksb");
			ctx.channel().writeAndFlush(req);
		}

	}

}


至此,實現了簡單的客戶端服務端長連線。







相關推薦

Netty實現連線簡單例子

Netty實現長連線的簡單例子 服務端 NettyServerBootstrap提供長連線服務 public class NettyServerBootstrap { private static final Log log = LogFactory.getLog(Ne

netty 實現連線,心跳機制,以及重連

實現的功能 心跳機制 and 長連線 and 重連機制 and 應用訊息傳輸: 這裡最關鍵的就是通過netty中的 IdleStateHandler 超時機制來實現心跳和重連 然後通過org.msgpack編碼器來實現跨平臺資料傳輸, 在這實現的功能就是通過Scanner來輸

Java後端實現websocket與微信小程式端連線簡單例子

} 以上是網上的前端及後端的程式碼(原文地址:http://www.cnblogs.com/xdp-gacl/p/5193279.html?utm_source=tuicool&utm_medium=referral),jdk版本要求是在jdk1.7.0以上,tomcat版本也需要在tomcat7.0

基於 django 實現的 webssh 簡單例子

exce attr index tar sum thread 命名 ssh 項目 說明 新建一個 django 程序,本文為 chain。 以下僅為簡單例子,實際應用 可根據自己平臺情況 進行修改。 打開首頁後,需要輸入1,後臺去登錄主機,然後返回登錄結果。 正常項目 可

JavaScript WebSocket實現連線通訊連線重連

JavaScript-JS依靠WebSoket也可以像其他語言一樣能夠實現通訊程式碼,不過使用的時候需要注意檢查連線斷開的情況。最基本的必須保證IP和埠都可以訪問。 目錄 WebSocket程式碼及測試 呼叫初始化程式碼 通訊示例程式碼 測試效果 WebSocket連線關

使用兩個棧實現佇列,簡單例子

棧, 取值是先進後出 ,後進先出。 那麼怎麼能按照佇列方式(先進先出)存值後取值呢? 看以下程式碼: import java.util.Stack; /** * @Author : JCccc * @Description : * @Point: Keep a good mood

iOS使用GCDSocketManager實現連線

.h檔案 #import <Foundation/Foundation.h> #import "GCDAsyncSocket.h" @interface GCDSocketManager : NSObject @property(nonatomic,strong) GCDAsyncSocket

Android之通過socket.io實現連線

在專案開發中,時常有服務端向客戶端主動發起交流的需求,可以整合極光推送,但是如果網路不好的情況下,推送可能會遲遲收不到,這樣就導致了使用者體驗得不到保證。 若改用socket實現長連線的話,速度就快很

網路程式設計知識(5)--用Netty實現的一個簡單的HTTP伺服器

用Netty實現的一個簡單的HTTP伺服器,可以處理靜態檔案,例子中的註釋也比較全。 public class HttpServer { public static void main(String[] args) {

高效 實現連線保活:手把手教你實現 自適應的心跳保活機制

以下內容轉載自http://blog.csdn.net/carson_ho/article/details/79522975前言當實現具備實時性需求時,我們一般會選擇長連線的通訊方式而在實現長連線方式時,存在很多效能問題,如 長連線保活今天,我將 手把手教大家實現自適應的心跳

使用OkHttp之Websocket實現連線

最近因為專案中用到了長連線,本來打算使用Socket,無意間發現了Websocket,實現起來很方便。 首先在在build.gradle中新增對Okhttp的支援 compile 'com.squareup.okhttp3:okhttp:3.8.1'

Netty實現客戶端和服務端通信簡單例子

啟動服務 ali tty 過程 等等 服務器初始化 讀寫操作 extends ask Netty是建立在NIO基礎之上,Netty在NIO之上又提供了更高層次的抽象。 在Netty裏面,Accept連接可以使用單獨的線程池去處理,讀寫操作又是另外的線程池來處理。 Accep

Android實現Socket連線 , OkSocket框架簡單使用

一個Android輕量級Socket通訊框架,既OkHttp後又一力作. 框架開源地址: https://github.com/xuuhaoo/OkSocket OkSocket簡介 Android OkSocket是一款基於阻塞式傳統Socket的一款Socket客戶端整體解決方案.您

netty實現TCP連線

所用jar包 netty-all-4.1.30.Final.jar 密碼:rzwe NettyConfig.java,存放連線的客戶端 1 import io.netty.channel.group.ChannelGroup; 2 import io.netty.channel.gr

Android推送的核心原理:連線簡單實現

實際需求 移動端需要實時的獲取伺服器的資料 解決方案 輪詢方式:應用程式開啟定時的輪詢,不停的向伺服器請求資料。 SMS push:傳送二進位制簡訊到移動終端,來達到通知終端的目的。客戶端攔截這類簡訊,然後採取相應的操作 持久連線方式:應用程式與伺服

Netty實現服務端客戶端連線通訊及心跳檢測

通過netty實現服務端與客戶端的長連線通訊,及心跳檢測。       基本思路:netty服務端通過一個Map儲存所有連線上來的客戶端SocketChannel,客戶端的Id作為Map的key。每次伺服器端如果要向某個客戶端傳送訊息,只需根據ClientId取出對應的So

(原創)Maven+Spring+CXF+Tomcat7 簡單例子實現webservice

produces per back targe xsd lean listener ans 控制 這個例子需要建三個Maven項目,其中一個為父項目,另外兩個為子項目 首先,建立父項目testParent,選擇quickstart: 輸入項目名稱和模塊名稱,然後創建:

用socket.io實現websocket的一個簡單例子

soc .html www sock 在線 ket log html 簡單例子 http://biyeah.iteye.com/blog/1295196 socket.io的介紹 http://www.cnblogs.com/mazg/p/5467960.html

Netty實現簡單UDP服務器

rec nal req 參考 syn group out equal 文件 本文參考《Netty權威指南》 文件列表: ├── ChineseProverbClientHandler.java ├── ChineseProverbClient.java ├── Chine

使用java實現快速排序的一個簡單例子

fast val rgs 快速 實現 個數 static void sta public static void main(String[] args) { // 測試排序 Random r = new Random(); int arr[] = new