거꾸로 바라본 세상
article thumbnail
반응형

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스트림을 이용해야한다.(서버와 클라이언트 동일)


User user = new User("hong", 25);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(user);
byte[] bs = bos.toByteArray();


바이트 배열로 변환하구 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
profile

거꾸로 바라본 세상

@란지에。

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!