0. 공통사항
- Object 타입 객체를 하나 만들었다.
작업환경 : 스프링 4.2.5, netty 4.1.0final 로함/
* 패키지와 임포트는 생략.
(1) User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String id; private int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(String id, int age) { super(); this.id = id; this.age = age; } @Override public String toString() { return "User [id=" + id + ", age=" + age + "]"; } } | cs |
(2). 서버 메인
1 2 3 4 5 6 7 8 9 | public class ServerMain { public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class); EchoServer echoServer = ctx.getBean("echoServer",EchoServer.class); echoServer.start(); ctx.close(); } } | cs |
1. Object객체 를 서버에 전송하기
오브젝트 타입의 데이터를 전송하려면 네티에서 제공하는 ObjectDecoder와 ObjectEncoder을 클라이언트와 서버 부트스트랩에 설정을 해주어야한다. 그럼 전송됨.
ch.pipeline().addLast(new ObjectDecoder( 1024 * 1024,
ClassResolvers
.weakCachingConcurrentResolver(this
.getClass()
.getClassLoader())),new ObjectEncoder());
(1) EchoServer.java
- 서버 부트스트랩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | public class EchoServer { private final int port; /* public static void main(String[] args) throws Exception { new EchoServer(9190).start(); }*/ @Autowired public EchoServer(int port) { this.port = port; } public void start() throws Exception { final EchoServerHandler serverHandler = new EchoServerHandler(); EventLoopGroup parentGroup = new NioEventLoopGroup(1); EventLoopGroup childGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(parentGroup, childGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ObjectDecoder( 1024 * 1024, ClassResolvers .weakCachingConcurrentResolver(this .getClass() .getClassLoader())),new ObjectEncoder()); ch.pipeline().addLast(serverHandler); } }); ChannelFuture future=bootstrap.bind(port).sync(); future.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { childGroup.shutdownGracefully().sync(); parentGroup.shutdownGracefully().sync(); } } } | cs |
(2). EchoClient.java
- 클라이언트 부트스트랩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public class EchoClient { private final String host; private final int port; public static void main(String[] args) throws Exception { new EchoClient("localhost", 9190).start(); } public EchoClient(String host, int port) { this.host = host; this.port = port; } public void start() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ObjectDecoder( 1024 * 1024, ClassResolvers .weakCachingConcurrentResolver(this .getClass() .getClassLoader())),new ObjectEncoder()); ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture f= bootstrap.connect(host,port).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { group.shutdownGracefully().sync(); } } } | cs |
(3)서버 핸들러
- 핸들러는 아래 처럼 msg를 User 객체를 통해 받아오면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class EchoServerHandler extends SimpleChannelInboundHandler<User>{ @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { User user = msg; System.out.println(user); user.setAge(30); ChannelFuture cf = ctx.writeAndFlush(user); cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(future.isSuccess()) { System.out.println("서버에서 전송 성공"); } else { System.out.println("서버에서 전송 실패"); } } }); } public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } | cs |
(4) 클라이언트 핸들러
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class EchoClientHandler extends SimpleChannelInboundHandler<User>{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { User user = new User("hong", 25); ChannelFuture cf= ctx.writeAndFlush(user); cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(future.isSuccess()) { System.out.println("클라이언트에서 전송성공"); } else { System.out.println("클라이언트에서 전송실패"); } } }); } @Override protected void channelRead0(ChannelHandlerContext ctx, User msg) throws Exception { User user = msg; System.out.println(user); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } | cs |
2. Object객체를 ByteBuf로 변환하여 전송하기
- ByteBuf 로 변환하여 전송할 때는 ObjectEncoder와 ObjectDecoder가 필요 없다. 그래서 빼버림.
(1) 부트스트랩 서버
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class EchoServer { private final int port; /* public static void main(String[] args) throws Exception { new EchoServer(9190).start(); }*/ @Autowired public EchoServer(int port) { this.port = port; } public void start() throws Exception { final EchoServerHandler serverHandler = new EchoServerHandler(); EventLoopGroup parentGroup = new NioEventLoopGroup(1); EventLoopGroup childGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(parentGroup, childGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(serverHandler); } }); ChannelFuture future=bootstrap.bind(port).sync(); future.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { childGroup.shutdownGracefully().sync(); parentGroup.shutdownGracefully().sync(); } } } | cs |
(2) 부트스트랩 클라이언트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class EchoClient { private final String host; private final int port; public static void main(String[] args) throws Exception { new EchoClient("localhost", 9190).start(); } public EchoClient(String host, int port) { this.host = host; this.port = port; } public void start() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture f= bootstrap.connect(host,port).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { group.shutdownGracefully().sync(); } } } | cs |
(3) 서버 핸들러
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | public class EchoServerHandler extends SimpleChannelInboundHandler<ByteBuf>{ @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { ByteBuf buf = msg; int length = buf.readableBytes(); System.out.println(msg + " length :" +length ); byte[] yous = new byte[length]; for(int i=0; i<length; i++) { yous[i] = buf.getByte(i); } ByteArrayInputStream bis = new ByteArrayInputStream(yous); ObjectInputStream ois = new ObjectInputStream(bis); User user = (User)ois.readObject(); ois.close(); bis.close(); System.out.println(user); //////////////////////// user.setId("change"); user.setAge(55); System.out.println("change: "+user); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(user); oos.close(); baos.close(); byte[] wrt = baos.toByteArray(); ByteBuf writebuf = Unpooled.directBuffer(); writebuf.writeBytes(wrt); ChannelFuture cf = ctx.writeAndFlush(writebuf); cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(future.isSuccess()) { System.out.println("서버에서 전송 성공"); } else { System.out.println("서버에서 전송 실패"); } } }); } public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } | cs |
(4) 클라이언트 핸들러
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf>{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { User user = new User("hong", 25); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(user); byte[] bs = bos.toByteArray(); ByteBuf buf = Unpooled.directBuffer(); buf.writeBytes(bs); System.out.println(buf.toString()); ChannelFuture cf =ctx.writeAndFlush(buf); cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(future.isSuccess()) { System.out.println("클라이언트에서 전송성공"); } else { System.out.println("클라이언트에서 전송실패"); } } }); } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { ByteBuf readbyte = msg; int length = readbyte.readableBytes(); System.out.println(readbyte + ", length : "+ length); byte[] read = new byte[length]; for(int i=0; i<length; i++) { read[i] = readbyte.getByte(i); } ByteArrayInputStream bis = new ByteArrayInputStream(read); ObjectInputStream ois = new ObjectInputStream(bis); User user = (User)ois.readObject(); System.out.println("client receive : "+ user); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } | cs |
- 전송을 하기위해서는 먼저 오브젝트 타입의 객체를 바이이트로 변환해야한다
그러기 위해서는 ObjectOutputStream과 ByteArrayOutput스트림을 이용해야한다.(서버와 클라이언트 동일)
바이트 배열로 변환하구 ByteBuf에 데이터를 저장 후 전송한다.(다이렉터버퍼이용함)
ByteBuf buf = Unpooled.directBuffer();
buf.writeBytes(bs);
ChannelFuture cf =ctx.writeAndFlush(buf);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
System.out.println("클라이언트에서 전송성공");
}
else {
System.out.println("클라이언트에서 전송실패");
}
}
});
전송한 ByteBuf는 다시 byte[] 배열에 넣고 ByteArrayInputStream과 ObjectInputStream을 이용하여 다시 객체화를 시킨다.(역직렬화라구 함)
ByteBuf readbyte = msg;
int length = readbyte.readableBytes();
System.out.println(readbyte + ", length : "+ length);
byte[] read = new byte[length];
for(int i=0; i<length; i++) {
read[i] = readbyte.getByte(i);
}
ByteArrayInputStream bis = new ByteArrayInputStream(read);
ObjectInputStream ois = new ObjectInputStream(bis);
User user = (User)ois.readObject();
System.out.println("client receive : "+ user);
서버에서 받은 결과
클라이언트에서 받은 결과
그럼 결과를 주고니 받고니 할 수 있다아~~~
끗
'Back-End > Netty' 카테고리의 다른 글
[Netty]네티서버에 필요한 요소 (0) | 2017.04.14 |
---|---|
[Netty] @Sharable (0) | 2017.04.13 |
[Netty] 1. 네티 프레임워크 (0) | 2017.04.13 |
[Netty] 네티 ServerBootstrap 만들기 (0) | 2016.04.06 |