- 浏览: 492508 次
- 性别:
- 来自: 广州
最新评论
-
cppmule:
Play!在国内实际产品级应用案例有吗?有哪些公司在用?国外的 ...
play总结性介绍 -
你好javaword:
netty的个人使用心得 -
hyfwuhui:
java 并发环境下使用ConcurrentHashMap -
asialee:
朋在无锡 写道可以将Channels使用静态导入的方式:imp ...
netty的个人使用心得 -
朋在无锡:
可以将Channels使用静态导入的方式:import sta ...
netty的个人使用心得
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
如果需要客户端和服务器端沟通 分别都需要编写一个 实现了SimpleChannelHandler接口的类,其中类中需要重写的主要方法为
channelConnected() and channelOpen() 这两个方法为 当客户端链接到服务器端得时候和 客户端 channel被创建出来的时候所调用的
channelDisconnected and channelClosed() 对应上面的两个方法
exceptionCaught 可以获得 对应handler端(服务器或客户端)的异常信息
messageReceived 每个 客户端 发送的信息后 将调用此方法
当编写完某端得程序后(客户端或服务器端) 将编写好的handler需要配置在 实现了ChannelPipelineFactory的类里,ChannelPipelineFactory中有一个需要实现的方法getPipeline将写好的handler配置到其中,在这个 工厂里 可能要添加很多东西
比如说 编解码器,心跳等。。。。
如需要自定义编解码器需要继承:LengthFieldBasedFrameDecoder(解码),OneToOneEncoder(编码)
编解码器(encode,decode)
encode为 调用messageReceived 方法之后调用的方法,则decode方法为 messageReceived 之前调用的方法 ,用于处理自定义包协议的解析于编辑
心跳: 当客户端socket在非正常情况家掉线,如: 断网,断电等特殊问题的时候, 客户端的channel对象不会自动关闭,需要一直接收到客户端的消息,从而判断是否可以和对象构成通信。。 如果 发现客户端空闲时间过长则视为掉线
服务端handler代码如下
package com.djyou.server;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ChildChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
public class ChatServerHandler extends SimpleChannelHandler{
public static final ChannelGroup channelGroup = new DefaultChannelGroup();
public int id;
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
System.out.println("进来一个");
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
super.channelDisconnected(ctx, e);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
Logger.getAnonymousLogger().info(e.getCause().getMessage());
ctx.getChannel().close();
// TODO Auto-generated method stub
//super.exceptionCaught(ctx, e);
}
@Override
public void childChannelClosed(ChannelHandlerContext ctx,
ChildChannelStateEvent e) throws Exception {
super.childChannelClosed(ctx, e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
System.out.println(this.id++);
//google protocol解码后返回为 ChannelBuffer类型
if(!(e.getMessage() instanceof ChannelBuffer)) return;
//获得 消息对象
ChannelBuffer channelBuffer = (ChannelBuffer)e.getMessage();
//MessageInfo info = Message.MessageInfo.newBuilder().mergeFrom(channelBuffer.copy().array()).build();
//写回给客户端
e.getChannel().write(channelBuffer);
}
}
pieplelineFactory里的代码为
package com.djyou.server;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.Timer;
public class ChatPipelineServerFactory implements ChannelPipelineFactory{
private Timer timer;
public ChatPipelineServerFactory(Timer timer){
this.timer = timer;
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
//添加netty默认支持的 编解码器(可自动添加包头,并处理粘包问题)
pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());//对应
pipeline.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());//此对象为 netty默认支持protocolbuf的编解码器
pipeline.addLast("timeout", new IdleStateHandler(timer, 10, 10, 0));//此两项为添加心跳机制 10秒查看一次在线的客户端channel是否空闲,IdleStateHandler为netty jar包中提供的类
pipeline.addLast("hearbeat", new Heartbeat());//此类 实现了IdleStateAwareChannelHandler接口
//netty会定时扫描 空闲的channel
//pipeline.addLast("frameDecoder", new ProtobufDecoder(Message.MessageInfo.getDefaultInstance()));
//pipeline.addLast("frameEncoder", new ProtobufEncoder());//
pipeline.addLast("handler", new ChatServerHandler());//将编写好的服务器端的handler添加到这里
return pipeline;
}
}
心跳包的代码如下
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
public class Heartbeat extends IdleStateAwareChannelHandler{
int i = 0;
@Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
throws Exception {
// TODO Auto-generated method stub
super.channelIdle(ctx, e);
if(e.getState() == IdleState.WRITER_IDLE)
i++;
if(i==3){
e.getChannel().close();
System.out.println("掉了。");
}
}
}
自定义解码器代码
package com.djyou.server;
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.LengthFieldBasedFrameDecoder;
public class Decode extends LengthFieldBasedFrameDecoder{
public Decode(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
// TODO Auto-generated constructor stub
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
ChannelBuffer buffs = (ChannelBuffer)super.decode(ctx, channel, buffer);
return buffs;
}
}
自定义编码器代码
package com.djyou.server;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public class Encode extends OneToOneEncoder{
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel,
Object msg) throws Exception {
// TODO Auto-generated method stub
return null;
}
}
服务端启动代码
package com.djyou.server;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;
public class ChatServer {
public static void main(String[] args) {
ChannelFactory factory = new NioServerSocketChannelFactory(Executors
.newCachedThreadPool(), Executors.newCachedThreadPool(),
Runtime.getRuntime().availableProcessors() + 1);
Timer timer = new HashedWheelTimer();
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChatPipelineServerFactory(timer));
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.setOption("reuseAddress", true);
bootstrap.bind(new InetSocketAddress(6666));
}
}
客户端启动代码如下(除客户端启动代码意外 其余的东西都与服务器端一样 都需要编写对应的 编解码器,定时发送消息线程(10秒发个信息给服务端 确保channel不为空闲, 来对应心跳程序), 客户端的handler)
package com.djyou.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import com.djyou.protoBufModel.Message;
import com.djyou.protoBufModel.Message.MessageInfo;
public class ChatClient {
public static void main(String[] args) throws Exception{
String host = "localhost";
int port = 6666;
// Configure the client.
ChannelFactory factory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ClientBootstrap bootstrap = new ClientBootstrap(factory);
ChatPipelineClientFactory cpcf = new ChatPipelineClientFactory();
bootstrap.setPipelineFactory(cpcf);
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
System.exit(0);
}
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// for (;;) {
// String line = in.readLine();
// if (line == null) {
// break;
// }
//创建Builder
MessageInfo.Builder builder = MessageInfo.newBuilder();
builder.addBody(Message.Body.newBuilder().setKey("message").setValue("你在干什么?" + "/n").build());
//创建 赋值结束的 Build 并生成 MessageInfo对象
MessageInfo messageInfo = builder.build();
//将messageInfo转换为字节
byte[] messageByte = messageInfo.toByteArray();
//获得此对象的长度
ChannelBuffer channelBuffer = ChannelBuffers.buffer(messageByte.length);
//将 获得到的数组写入 channelBuffer中
channelBuffer.writeBytes(messageByte);
//发送到服务器端
for(int i = 0; i < 10;i++){
lastWriteFuture = channel.write(channelBuffer);
}
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
// }
// Thread.sleep(50000);
// Wait until all messages are flushed before closing the channel.
Thread.sleep(50000);
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
channel.close().awaitUninterruptibly();
// We should shut down all thread pools here to exit normally.
// However, it is just fine to call System.exit(0) because we are
// finished with the business.
System.exit(0);
}
}
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
的确是这样,但是特别容易忽略,静态导入的位置和方式比较难注意到,我也是一行行对比代码才发现。
是呀,静态导入有这样的问题
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
的确是这样,但是特别容易忽略,静态导入的位置和方式比较难注意到,我也是一行行对比代码才发现。
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
如果需要客户端和服务器端沟通 分别都需要编写一个 实现了SimpleChannelHandler接口的类,其中类中需要重写的主要方法为
channelConnected() and channelOpen() 这两个方法为 当客户端链接到服务器端得时候和 客户端 channel被创建出来的时候所调用的
channelDisconnected and channelClosed() 对应上面的两个方法
exceptionCaught 可以获得 对应handler端(服务器或客户端)的异常信息
messageReceived 每个 客户端 发送的信息后 将调用此方法
当编写完某端得程序后(客户端或服务器端) 将编写好的handler需要配置在 实现了ChannelPipelineFactory的类里,ChannelPipelineFactory中有一个需要实现的方法getPipeline将写好的handler配置到其中,在这个 工厂里 可能要添加很多东西
比如说 编解码器,心跳等。。。。
如需要自定义编解码器需要继承:LengthFieldBasedFrameDecoder(解码),OneToOneEncoder(编码)
编解码器(encode,decode)
encode为 调用messageReceived 方法之后调用的方法,则decode方法为 messageReceived 之前调用的方法 ,用于处理自定义包协议的解析于编辑
心跳: 当客户端socket在非正常情况家掉线,如: 断网,断电等特殊问题的时候, 客户端的channel对象不会自动关闭,需要一直接收到客户端的消息,从而判断是否可以和对象构成通信。。 如果 发现客户端空闲时间过长则视为掉线
服务端handler代码如下
package com.djyou.server;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ChildChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
public class ChatServerHandler extends SimpleChannelHandler{
public static final ChannelGroup channelGroup = new DefaultChannelGroup();
public int id;
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
System.out.println("进来一个");
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
super.channelDisconnected(ctx, e);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
Logger.getAnonymousLogger().info(e.getCause().getMessage());
ctx.getChannel().close();
// TODO Auto-generated method stub
//super.exceptionCaught(ctx, e);
}
@Override
public void childChannelClosed(ChannelHandlerContext ctx,
ChildChannelStateEvent e) throws Exception {
super.childChannelClosed(ctx, e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
System.out.println(this.id++);
//google protocol解码后返回为 ChannelBuffer类型
if(!(e.getMessage() instanceof ChannelBuffer)) return;
//获得 消息对象
ChannelBuffer channelBuffer = (ChannelBuffer)e.getMessage();
//MessageInfo info = Message.MessageInfo.newBuilder().mergeFrom(channelBuffer.copy().array()).build();
//写回给客户端
e.getChannel().write(channelBuffer);
}
}
pieplelineFactory里的代码为
package com.djyou.server;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.Timer;
public class ChatPipelineServerFactory implements ChannelPipelineFactory{
private Timer timer;
public ChatPipelineServerFactory(Timer timer){
this.timer = timer;
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
//添加netty默认支持的 编解码器(可自动添加包头,并处理粘包问题)
pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());//对应
pipeline.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());//此对象为 netty默认支持protocolbuf的编解码器
pipeline.addLast("timeout", new IdleStateHandler(timer, 10, 10, 0));//此两项为添加心跳机制 10秒查看一次在线的客户端channel是否空闲,IdleStateHandler为netty jar包中提供的类
pipeline.addLast("hearbeat", new Heartbeat());//此类 实现了IdleStateAwareChannelHandler接口
//netty会定时扫描 空闲的channel
//pipeline.addLast("frameDecoder", new ProtobufDecoder(Message.MessageInfo.getDefaultInstance()));
//pipeline.addLast("frameEncoder", new ProtobufEncoder());//
pipeline.addLast("handler", new ChatServerHandler());//将编写好的服务器端的handler添加到这里
return pipeline;
}
}
心跳包的代码如下
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
public class Heartbeat extends IdleStateAwareChannelHandler{
int i = 0;
@Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
throws Exception {
// TODO Auto-generated method stub
super.channelIdle(ctx, e);
if(e.getState() == IdleState.WRITER_IDLE)
i++;
if(i==3){
e.getChannel().close();
System.out.println("掉了。");
}
}
}
自定义解码器代码
package com.djyou.server;
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.LengthFieldBasedFrameDecoder;
public class Decode extends LengthFieldBasedFrameDecoder{
public Decode(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
// TODO Auto-generated constructor stub
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
ChannelBuffer buffs = (ChannelBuffer)super.decode(ctx, channel, buffer);
return buffs;
}
}
自定义编码器代码
package com.djyou.server;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public class Encode extends OneToOneEncoder{
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel,
Object msg) throws Exception {
// TODO Auto-generated method stub
return null;
}
}
服务端启动代码
package com.djyou.server;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;
public class ChatServer {
public static void main(String[] args) {
ChannelFactory factory = new NioServerSocketChannelFactory(Executors
.newCachedThreadPool(), Executors.newCachedThreadPool(),
Runtime.getRuntime().availableProcessors() + 1);
Timer timer = new HashedWheelTimer();
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChatPipelineServerFactory(timer));
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.setOption("reuseAddress", true);
bootstrap.bind(new InetSocketAddress(6666));
}
}
客户端启动代码如下(除客户端启动代码意外 其余的东西都与服务器端一样 都需要编写对应的 编解码器,定时发送消息线程(10秒发个信息给服务端 确保channel不为空闲, 来对应心跳程序), 客户端的handler)
package com.djyou.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import com.djyou.protoBufModel.Message;
import com.djyou.protoBufModel.Message.MessageInfo;
public class ChatClient {
public static void main(String[] args) throws Exception{
String host = "localhost";
int port = 6666;
// Configure the client.
ChannelFactory factory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ClientBootstrap bootstrap = new ClientBootstrap(factory);
ChatPipelineClientFactory cpcf = new ChatPipelineClientFactory();
bootstrap.setPipelineFactory(cpcf);
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
System.exit(0);
}
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// for (;;) {
// String line = in.readLine();
// if (line == null) {
// break;
// }
//创建Builder
MessageInfo.Builder builder = MessageInfo.newBuilder();
builder.addBody(Message.Body.newBuilder().setKey("message").setValue("你在干什么?" + "/n").build());
//创建 赋值结束的 Build 并生成 MessageInfo对象
MessageInfo messageInfo = builder.build();
//将messageInfo转换为字节
byte[] messageByte = messageInfo.toByteArray();
//获得此对象的长度
ChannelBuffer channelBuffer = ChannelBuffers.buffer(messageByte.length);
//将 获得到的数组写入 channelBuffer中
channelBuffer.writeBytes(messageByte);
//发送到服务器端
for(int i = 0; i < 10;i++){
lastWriteFuture = channel.write(channelBuffer);
}
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
// }
// Thread.sleep(50000);
// Wait until all messages are flushed before closing the channel.
Thread.sleep(50000);
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
channel.close().awaitUninterruptibly();
// We should shut down all thread pools here to exit normally.
// However, it is just fine to call System.exit(0) because we are
// finished with the business.
System.exit(0);
}
}
评论
7 楼
你好javaword
2014-10-17
6 楼
asialee
2013-10-18
朋在无锡 写道
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
的确是这样,但是特别容易忽略,静态导入的位置和方式比较难注意到,我也是一行行对比代码才发现。
是呀,静态导入有这样的问题
5 楼
朋在无锡
2013-10-18
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
的确是这样,但是特别容易忽略,静态导入的位置和方式比较难注意到,我也是一行行对比代码才发现。
4 楼
asialee
2013-09-13
朋在无锡 写道
ChannelPipeline pipeline = pipeline();
这个漏掉了,对于菜鸟来说影响很大,希望后来者注意,
正确如下:
ChannelPipeline pipeline =Channels.pipeline();
这个漏掉了,对于菜鸟来说影响很大,希望后来者注意,
正确如下:
ChannelPipeline pipeline =Channels.pipeline();
可以将Channels使用静态导入的方式:
import static org.jboss.netty.channel.Channels;
3 楼
朋在无锡
2013-09-11
ChannelPipeline pipeline = pipeline();
这个漏掉了,对于菜鸟来说影响很大,希望后来者注意,
正确如下:
ChannelPipeline pipeline =Channels.pipeline();
这个漏掉了,对于菜鸟来说影响很大,希望后来者注意,
正确如下:
ChannelPipeline pipeline =Channels.pipeline();
2 楼
asialee
2013-02-20
博主这块写的挺好的,我完全看了,不过我也写了一些关于编解码器的,请批评指正http://asialee.iteye.com/blog/1769508
1 楼
chxiaowu
2012-06-14
Good!
发表评论
-
netty4更新详解
2015-11-14 10:52 615netty现在应该是java界最流行的网络框架之一了,高性能, ... -
Lua使用protocolbuf
2015-11-10 16:04 836在https://code.google.com/p/prot ... -
领域模型设计
2015-09-12 17:29 657一:面向对象设计中最简单的部分与最难的部分 如果说事务脚本是 ... -
关于分表与分库思路
2015-07-06 15:36 552首先主要实现应该参考开源产品,目前比较能上台面的是 tddl, ... -
NAT穿透解决方案介绍
2015-04-01 03:12 1960最近公司要实现在各种网络环境下面的多屏互动(机顶盒、andro ... -
音视频即时通讯开发中使用P2P技术的好处
2015-04-01 02:59 719在服务器的配置文件“A ... -
nat穿透原理
2015-04-01 02:01 1025一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技 ... -
Erlang学习记录(二)——基本数据类型
2015-03-30 03:51 424Erlang学习记录(二)—— ... -
集群、分布式、负载均衡区别与联系
2015-03-25 22:54 5611、Linux集群主要分成三 ... -
: 结构化数据的共享存储
2015-03-24 04:25 0开发笔记 (6) : 结构化数据的共享存储 开始这个话题前, ... -
:如何构建超强伸缩性的游戏服务器而集容错、负载均衡和无限伸缩性于一身
2015-03-24 04:04 875附标题:如何构建超强 ... -
edis在游戏服务器中的应用
2015-03-24 02:57 594edis在游戏服务器中的应 ... -
社交游戏之双机热备方案 预防单点故障
2015-03-23 04:46 848某一天深夜,单盘配置的服务器出现硬盘损坏,导致该服务器上所提 ... -
游戏服务器集群设计思路
2015-03-23 04:45 761对于我们的游戏服务器端来说,除了要满足一般的MMO服务 ... -
Erlang类型及函数声明规格
2015-03-04 14:33 626Erlang类型及函数声明规格 Author: Mail: ... -
(转)erlang lists模块函数使用大全
2015-02-12 16:26 537一,带函数Pred 1, all(Pred ... -
超越并行框架erlang之流的通讯框架
2015-02-05 17:41 591http://blog.codingnow.com/2011/ ... -
如何使用 Oracle Linux 中的硬件故障管理
2014-11-10 14:38 1390如何使用 Oracle Linux 中 ... -
配置nginx
2014-06-14 18:04 561http://www.cnblogs.com/wenanry/ ... -
centos 安装mysql
2014-06-13 12:23 567你是root權限嗎?_操作系統的_ 兩種方法 1 使用替換法 ...
相关推荐
Netty在Android开发中的应用实战系列(二)——— Encoder | Decoder | Handler 的使用:https://azhon.blog.csdn.net/article/details/100831777 Netty在Android开发中的应用实战系列(三)——— 心跳处理 | 断线...
NettyDemo Netty使用实例,对象传递调用; LineBasedFrameDecoder + 消息中得换行符;解决TCP 粘包问题; Java序列化方案编解码对比;对象调用方案
Netty使用与实现.pdf
Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码;Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码;Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码
主要是netty长连接在Android中的使用,demo只是简单的实现了客户端和服务端的数据交互。如果要使用还需要完善很多细节。
Netty实战
本资料是使用netty4来进行对象的传输的demo ,并对这个通信做了封装,方便用户的使用。
这个小程序使用netty5进行udp网络通讯,客户端有两种,1:用netty5类库发送DatagramPacket和接收 2:直接使用DatagramSocket发送接收DatagramPacket 先运行netty_server的QuoteOfTheMomentServer, 在运行netty_...
使用Netty, Disruptor处理实时外汇报价
Netty的UDP通信心得
java中使用netty包常见以及经常用到类说明: netty客户端配置及参数填写,常见类使用; netty服务端配置及参数填写,常见类使用;
使用netty进行rtsp服务端开发 一个使用netty写的rtsp服务器。 目前支持H264、H265、 AAC格式的流文件上传与存储。 H264、H265、AAC格式流文件的播放
Android Netty的简单使用,详情请看博客:https://blog.csdn.net/yuzhiqiang_1993/article/details/84390605
Android Studio 开发Netty网络访问框架,实现了客户端、服务端两种访问方式,支持发送心跳数据,使用Handler实现外部数据交互,有调用Demo,在实际项目中使用暂时没有问题
netty 物联网iot中mqtt 服务器端开发,主要是使用技术springboot+mqtt3.1.1+netty
spring+netty+mybatis整合实例 实现一个简单的socket服务,启动服务后,客户端发送一条消息,服务端从数据库查询数据并返回给客户端。
springboot集成netty,使用protobuf作为数据交换格式,可以用于智能终端云端服务脚手架。
java框架应用,以及优化使用。Netty是一个NIO客户端服务器框架,可以快速轻松地开发网络应用程序,例如协议服务器和客户端。它极大地简化和简化了TCP和UDP套接字服务器等网络编程。 “快速简便”并不意味着最终的...
netty部分解析
Netty基础,用于学习Netty,参考黑马程序员的netty教程