67,512
社区成员
发帖
与我相关
我的任务
分享
public class XLRequest {
private int length; // 数据包长
private Map<String,String> datas=new HashMap<String, String>(); //参数
。。。。。。。
}
public class MessageEncoder extends OneToOneEncoder {
public void encodeDataBuffer(Map<String, String> values, ChannelBuffer totalBuffer) throws Exception {
if (values != null && values.size() > 0) {
for (Entry<String, String> entry : values.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
totalBuffer.writeInt(key.getBytes().length);
totalBuffer.writeBytes(key.getBytes());
totalBuffer.writeInt(value.getBytes().length);
totalBuffer.writeBytes(value.getBytes());
}
}
}
public int getDataLength(Map<String, String> values){
int dataLength = 0;
for (Entry<String, String> entry : values.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
dataLength = dataLength + 4 + key.getBytes().length + 4
+ value.getBytes().length;
}
return dataLength;
}
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel,
Object msg) throws Exception {
XLRequest request = (XLRequest) msg;
ChannelBuffer totalBuffer = ChannelBuffers.dynamicBuffer();
Map<String, String> datas = request.getDatas();
if(datas==null || datas.isEmpty()){
throw new Exception("内容为空!");
}
totalBuffer.writeInt(getDataLength(datas));
encodeDataBuffer(datas, totalBuffer);
return totalBuffer;
}
}
public class MessageDecoder extends FrameDecoder {
public static final Logger logger = LoggerFactory.getLogger(MessageDecoder.class);
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
if (buffer.readableBytes() < 4) {
return null;
}
buffer.markReaderIndex();
int totalLength = buffer.readInt(); // 数据包长
if (buffer.readableBytes() < totalLength) {
buffer.resetReaderIndex();
return null;
}
ChannelBuffer dataBuffer = ChannelBuffers.buffer(totalLength);
buffer.readBytes(dataBuffer, totalLength);
XLRequest request = new XLRequest();
request.setLength(totalLength);
request.setDatas(decodeDataBuffer(dataBuffer));
return request;
}
public Map<String, String> decodeDataBuffer(ChannelBuffer dataBuffer ) throws IOException, Exception {
Map<String, String> dataMap = new HashMap<String, String>();
if (dataBuffer != null && dataBuffer.readableBytes() > 0) {
int processIndex = 0;
int totalLength = dataBuffer.readableBytes();
while (processIndex < totalLength) {
/**
* 获取Key
*/
int size = dataBuffer.readInt();
byte[] contents = new byte[size];
dataBuffer.readBytes(contents);
String key = new String(contents);
processIndex = processIndex + size + 4;
/**
* 获取Value
*/
size = dataBuffer.readInt();
contents = new byte[size];
dataBuffer.readBytes(contents);
String value = new String(contents);
dataMap.put(key, value);
processIndex = processIndex + size + 4;
}
}
return dataMap;
}
}
public XLRequest createSendData(Integer channelId) {
XLRequest request = new XLRequest();
if(firstCreated){
msg2_1024bytes = formResponseMessage(2);
msg5_1024bytes = formResponseMessage(5);
msg10_1024bytes = formResponseMessage(10);
msg50_1024bytes = formResponseMessage(50);
firstCreated = false;
}
String msg = getMessage(ConfigUtil.SEND_BYTES);
request.setValue("msg", msg);
request.setValue("sid", lastSid.getAndIncrement()+"");
request.setValue("time", System.currentTimeMillis()+"");
return request;
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent)
throws Exception {
XLRequest request = (XLRequest) messageEvent.getMessage();
request.setValue("recvTime", System.currentTimeMillis()+"");
messageManager.addSocketMessage(messageManager.handleMessage(CommandType.CLIENT_REQUEST,
ctx.getChannel(), request));
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
Channel channel = ctx.getChannel();
if (channel != null) {
// send data
XLRequest clientRequest = createSendData(channel.getId());
ClientSenderThread senderThread = new ClientSenderThread(channel, clientRequest);
Thread thread = new Thread(senderThread);
thread.start();
}
super.channelConnected(ctx, e);
}
public class ClientFactory implements ChannelPipelineFactory {
private MessageDecoder messageDecoder = new MessageDecoder();
private MessageEncoder messageEncoder = new MessageEncoder();
private ClientHandler clientHandler = new ClientHandler();
ExecutionHandler executionHandler = new ExecutionHandler(
new OrderedMemoryAwareThreadPoolExecutor(
SysInfo.getProcessors()*ConfigUtil.GATEWAY_PROCESS,
ConfigUtil.MAX_CHANNEL_MEMORY_SIZE,
0)
);
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline cp = Channels.pipeline();
cp.addLast("messageClientDecoder", messageDecoder);
cp.addLast("messageClientEncoder", messageEncoder);
cp.addLast("executionHandler", executionHandler);
cp.addLast("clientHandler", clientHandler);
return cp;
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent)
throws Exception {
Channel sendChannel = ctx.getChannel();
doProcessFromClient(ctx, messageEvent, sendChannel);
}
private void doProcessFromClient(ChannelHandlerContext ctx,
MessageEvent messageEvent, Channel sendChannel) {
XLRequest request = (XLRequest)messageEvent.getMessage();
byte command = CommandType.GATE_TO_CLIENT_NORMAL;
messageManager.addSocketMessage(messageManager.handleMessage(command, ctx.getChannel(), request));
}
GateWayFactory:
public class GatewayFactory implements ChannelPipelineFactory {
private MessageDecoder messageDecoder = new MessageDecoder();
private MessageEncoder messageEncoder = new MessageEncoder();
private GatewayMessageHandler gatewayMessageHandler = new GatewayMessageHandler();
ExecutionHandler executionHandler = new ExecutionHandler(
new OrderedMemoryAwareThreadPoolExecutor(
SysInfo.getProcessors()*ConfigUtil.GATEWAY_PROCESS,
ConfigUtil.MAX_CHANNEL_MEMORY_SIZE,
0)
);
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline cp = Channels.pipeline();
cp.addLast("messageServerDecoder", messageDecoder);
cp.addLast("messageServerEncoder", messageEncoder);
cp.addLast("executionHandler", executionHandler);
cp.addLast("gatewayMessageHandler", gatewayMessageHandler);
return cp;
}
}
消息队列:
public class MessageManager {
public static final Logger logger = LoggerFactory.getLogger(MessageManager.class);
/** MessageManager的消息队列,下面的addSocketMessage方法就是向这个队列塞MessagePack的*/
private LinkedBlockingQueue<MessagePack> receivedQueen = new LinkedBlockingQueue<MessagePack>();
private ExecutorService pool;
/** 登记式单例类 */
private static AtomicInteger instanceIndex = new AtomicInteger(0);
private static Map<String, MessageManager> instanceMap = new HashMap<String, MessageManager>();
private String instanceName = "";
public static final String INSTANCE_CLIENT_TO_GATE = "client_to_gate";
public static final String INSTANCE_GATE_TO_CLIENT = "gate_to_client";
private MessageManager(String name){
this.instanceName = name;
}
public String getInstanceName() {
return instanceName;
}
public static MessageManager getInstance(String name){
if(StringUtils.isBlank(name)){
name = MessageManager.class.getName().concat(instanceIndex.get()+"");
instanceIndex.getAndIncrement();
}
synchronized (instanceMap) {
MessageManager instance = instanceMap.get(name);
if(instance==null){
instance = new MessageManager(name);
instanceMap.put(name, instance);
}
return instance;
}
}
public MessagePack handleMessage(byte command, Channel sendChannel, XLRequest request) {
MessagePack messagePack = null;
switch (command) {
case CommandType.GATE_TO_CLIENT_NORMAL:
messagePack = new GateMessagePack(command, sendChannel, request);
break;
case CommandType.CLIENT_REQUEST:
messagePack = new ClientMessagePack(command, sendChannel, request);
}
return messagePack;
}
public void start() {
pool = Executors.newFixedThreadPool(SysInfo.getProcessors()*2);
for(int i=0;i<SysInfo.getProcessors();i++){
pool.execute(new PushRecvThread());
}
}
private class PushRecvThread implements Runnable {
public void run() {
while (true) {
// 从队列中取继承MessagePack的实例
MessagePack message;
try {
message = receivedQueen.poll(1, TimeUnit.MILLISECONDS);
if (message != null) {
message.onHandler();
}
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
}
public void addSocketMessage(MessagePack message) {
if (message != null) {
try {
boolean success = receivedQueen.offer(message, 1,TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
}
代码比较多,源代码我上传到百度网盘了,地址: http://pan.baidu.com/s/17Vbyg
7k用户每隔1s发送200byte数据的时候,就会出现如下的错误,而且还有个很奇怪的问题,在这7k用户建立连接的过程中,不会出现解码问题,全部建立连接后不久,就会出现解码问题。不知道是不是我写的代码有问题,各位大牛帮忙看看吧。
java.lang.IndexOutOfBoundsException: Not enough readable bytes - Need 4, maximum is 3
at org.jboss.netty.buffer.AbstractChannelBuffer.checkReadableBytes(AbstractChannelBuffer.java:661)
at org.jboss.netty.buffer.AbstractChannelBuffer.readInt(AbstractChannelBuffer.java:273)
at com.zltx.game.sky.net.verify.MessageDecoder.decodeDataBuffer(MessageDecoder.java:51)
at com.zltx.game.sky.net.verify.MessageDecoder.decode(MessageDecoder.java:37)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:425)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:310)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
java.lang.IndexOutOfBoundsException: Not enough readable bytes - Need 825570103, maximum is 0
at org.jboss.netty.buffer.AbstractChannelBuffer.checkReadableBytes(AbstractChannelBuffer.java:661)
at org.jboss.netty.buffer.AbstractChannelBuffer.readBytes(AbstractChannelBuffer.java:338)
at org.jboss.netty.buffer.AbstractChannelBuffer.readBytes(AbstractChannelBuffer.java:344)
at com.zltx.game.sky.net.verify.MessageDecoder.decodeDataBuffer(MessageDecoder.java:53)
at com.zltx.game.sky.net.verify.MessageDecoder.decode(MessageDecoder.java:37)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:425)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:310)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)