1、請求編碼器 RequestEncoder
package com.cn.codc;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import com.cn.constant.ConstantValue;
import com.cn.model.Request;
/**
* 請求編碼器
* <pre>
* 數據包格式
* +——----——+——-----——+——----——+——----——+——-----——+
* | 包頭 | 模塊號 | 命令號 | 長度 | 數據 |
* +——----——+——-----——+——----——+——----——+——-----——+
* </pre>
* 包頭4字節
* 模塊號2字節short
* 命令號2字節short
* 長度4字節(描述數據部分字節長度)
*
* @author
*
*/
public class RequestEncoder extends OneToOneEncoder{
@Override
protected Object encode(ChannelHandlerContext context, Channel channel, Object rs) throws Exception {
Request request = (Request)(rs);
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
//包頭
buffer.writeInt(ConstantValue.FLAG);
//module
buffer.writeShort(request.getModule());
//cmd
buffer.writeShort(request.getCmd());
//長度
buffer.writeInt(request.getDataLength());
//data
if(request.getData() != null){
buffer.writeBytes(request.getData());
}
return buffer;
}
}
2、請求解碼器 RequestDecoder
package com.cn.codc;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import com.cn.constant.ConstantValue;
import com.cn.model.Request;
/**
* 請求解碼器
* <pre>
* 數據包格式
* +——----——+——-----——+——----——+——----——+——-----——+
* | 包頭 | 模塊號 | 命令號 | 長度 | 數據 |
* +——----——+——-----——+——----——+——----——+——-----——+
* </pre>
* 包頭4字節
* 模塊號2字節short
* 命令號2字節short
* 長度4字節(描述數據部分字節長度)
*
* @author
*
*/
public class RequestDecoder extends FrameDecoder{
/**
* 數據包基本長度
*/
public static int BASE_LENTH = 4 + 2 + 2 + 4;
@Override
protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception {
//可讀長度必須大於基本長度
if(buffer.readableBytes() >= BASE_LENTH){
//防止socket字節流攻擊
if(buffer.readableBytes() > 2048){
buffer.skipBytes(buffer.readableBytes());
}
//記錄包頭開始的index
int beginReader;
while(true){
beginReader = buffer.readerIndex();
buffer.markReaderIndex();
if(buffer.readInt() == ConstantValue.FLAG){
break;
}
//未讀到包頭,略過一個字節
buffer.resetReaderIndex();
buffer.readByte();
//長度又變得不滿足
if(buffer.readableBytes() < BASE_LENTH){
return null;
}
}
//模塊號
short module = buffer.readShort();
//命令號
short cmd = buffer.readShort();
//長度
int length = buffer.readInt();
//判斷請求數據包數據是否到齊
if(buffer.readableBytes() < length){
//還原讀指針
buffer.readerIndex(beginReader);
return null;
}
//讀取data數據
byte[] data = new byte[length];
buffer.readBytes(data);
Request request = new Request();
request.setModule(module);
request.setCmd(cmd);
request.setData(data);
//繼續往下傳遞
return request;
}
//數據包不完整,需要等待後面的包來
return null;
}
}
3、response解碼器 ResponseDecoder
package com.cn.codc;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import com.cn.constant.ConstantValue;
import com.cn.model.Response;
/**
* response解碼器
* <pre>
* 數據包格式
* +——----——+——-----——+——----——+——----——+——-----——+——-----——+
* | 包頭 | 模塊號 | 命令號 | 狀態碼 | 長度 | 數據 |
* +——----——+——-----——+——----——+——----——+——-----——+——-----——+
* </pre>
* 包頭4字節
* 模塊號2字節short
* 命令號2字節short
* 長度4字節(描述數據部分字節長度)
*
* @author
*
*/
public class ResponseDecoder extends FrameDecoder{
/**
* 數據包基本長度
*/
public static int BASE_LENTH = 4 + 2 + 2 + 4;
@Override
protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception {
//可讀長度必須大於基本長度
if(buffer.readableBytes() >= BASE_LENTH){
//記錄包頭開始的index
int beginReader = buffer.readerIndex();
while(true){
if(buffer.readInt() == ConstantValue.FLAG){
break;
}
}
//模塊號
short module = buffer.readShort();
//命令號
short cmd = buffer.readShort();
//狀態碼
int stateCode = buffer.readInt();
//長度
int length = buffer.readInt();
if(buffer.readableBytes() < length){
//還原讀指針
buffer.readerIndex(beginReader);
return null;
}
byte[] data = new byte[length];
buffer.readBytes(data);
Response response = new Response();
response.setModule(module);
response.setCmd(cmd);
response.setStateCode(stateCode);
response.setData(data);
//繼續往下傳遞
return response;
}
//數據包不完整,需要等待後面的包來
return null;
}
}
4、響應編碼器 ResponseEncoder
package com.cn.codc;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import com.cn.constant.ConstantValue;
import com.cn.model.Response;
/**
* 響應編碼器
* <pre>
* 數據包格式
* +——----——+——-----——+——----——+——----——+——-----——+——-----——+
* | 包頭 | 模塊號 | 命令號 | 狀態碼 | 長度 | 數據 |
* +——----——+——-----——+——----——+——----——+——-----——+——-----——+
* </pre>
* 包頭4字節
* 模塊號2字節short
* 命令號2字節short
* 長度4字節(描述數據部分字節長度)
*
* @author
*
*/
public class ResponseEncoder extends OneToOneEncoder{
@Override
protected Object encode(ChannelHandlerContext context, Channel channel, Object rs) throws Exception {
Response response = (Response)(rs);
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
//包頭
buffer.writeInt(ConstantValue.FLAG);
//module
buffer.writeShort(response.getModule());
//cmd
buffer.writeShort(response.getCmd());
//狀態碼
buffer.writeInt(response.getStateCode());
//長度
buffer.writeInt(response.getDataLength());
//data
if(response.getData() != null){
buffer.writeBytes(response.getData());
}
return buffer;
}
}
5、netty server
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;
import com.cn.codc.RequestDecoder;
import com.cn.codc.ResponseEncoder;
/**
* netty服務端入門
* @author
*
*/
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 RequestDecoder());
pipeline.addLast("encoder", new ResponseEncoder());
pipeline.addLast("helloHandler", new HelloHandler());
return pipeline;
}
});
bootstrap.bind(new InetSocketAddress(10101));
System.out.println("start!!!");
}
}
6、netty client
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 com.cn.codc.RequestEncoder;
import com.cn.codc.ResponseDecoder;
import com.cn.model.Request;
import com.cn.module.fuben.request.FightRequest;
/**
* netty客戶端入門
* @author
*
*/
public class Client {
public static void main(String[] args) throws InterruptedException {
//服務類
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 ResponseDecoder());
pipeline.addLast("encoder", new RequestEncoder());
pipeline.addLast("hiHandler", new HiHandler());
return pipeline;
}
});
//連接服務端
ChannelFuture connect = bootstrap.connect(new InetSocketAddress("127.0.0.1", 10101));
Channel channel = connect.sync().getChannel();
System.out.println("client start");
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("請輸入");
int fubenId = Integer.parseInt(scanner.nextLine());
int count = Integer.parseInt(scanner.nextLine());
FightRequest fightRequest = new FightRequest();
fightRequest.setFubenId(fubenId);
fightRequest.setCount(count);
Request request = new Request();
request.setModule((short) 1);
request.setCmd((short) 1);
request.setData(fightRequest.getBytes());
//發送請求
channel.write(request);
}
}
}