src/nettystartup/h3/ChatServer.java
public final class ChatServer {
public static void main(String[] args) throws Exception {
NettyStartupUtil.runServer(8030, new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new LineBasedFrameDecoder(1024, true, true))
.addLast(new StringDecoder(CharsetUtil.UTF_8),
new StringEncoder(CharsetUtil.UTF_8))
.addLast(new ChatMessageCodec(),
new LoggingHandler(LogLevel.INFO))
.addLast(new ChatServerHandler());
}
});
}
}
LineBasedDecoder, StringDecoder, StringDecoder는 마지막 시간에 설명
src/nettystartup/h3/ChatMessage.java
public class ChatMessage {
public final String command;
public final String nickname;
public String text;
public String toString() { ... }
public static ChatMessage parse(String line) { ... }
...
}
src/nettystartup/h3/ChatServerHandler.java (1)
public class ChatServerHandler extends SimpleChannelInboundHandler<ChatMessage> {
private static final ChannelGroup channels =
new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
public void channelActive(ChannelHandlerContext ctx) {
helo(ctx.channel());
}
public void channelInactive(final ChannelHandlerContext ctx) {
channels.remove(ctx.channel());
channels.writeAndFlush(M("LEFT", nickname(ctx)));
nicknameProvider.release(nickname(ctx));
}
... 다음 슬라이드에 계속 ...
}
src/nettystartup/h3/ChatServerHandler.java (2)
public class ChatServerHandler extends ... {
...
public void helo(Channel ch) {
if (nickname(ch) != null) return; // already done;
String nick = nicknameProvider.reserve();
if (nick == null) {
ch.writeAndFlush(M("ERR", "sorry, no more names for you"))
.addListener(ChannelFutureListener.CLOSE);
} else {
bindNickname(ch, nick);
channels.forEach(c -> ch.write(M("HAVE", nickname(c))));
channels.writeAndFlush(M("JOIN", nick));
channels.add(ch);
ch.writeAndFlush(M("HELO", nick));
}
}
...
}
src/nettystartup/h3/ChatServerHandler.java (3)
public class ChatServerHandler extends SimpleChannelInboundHandler<ChatMessage> {
... 이전 슬라이드에서 이어짐 ...
protected void channelRead0(ChannelHandlerContext ctx, ChatMessage msg) throws Exception {
if ("PING".equals(msg.command)) {
// TODO: [실습3-1] PING 명령어에 대한 응답을 내보냅니다
} else if ("QUIT".equals(msg.command)) {
// TODO: [실습3-2] QUIT 명령어를 처리하고 BYE를 응답합니다. 연결도 끊습니다.
} else if ("SEND".equals(msg.command)) {
// TODO: [실습3-3] 클라이언트로부터 대화 텍스트가 왔습니다. 모든 채널에 방송합니다.
} else if ("NICK".equals(msg.command)) {
changeNickname(ctx, msg);
} else {
ctx.write(M("ERR", null, "unknown command -> " + msg.command));
}
}
}
src/nettystartup/h3/ChatMessageCodec.java
ChatMessage
와 String
간 변환 담당
class ChatMessageCodec extends MessageToMessageCodec<String, ChatMessage> {
@Override
protected void encode(C..H..Context ctx, ChatMessage msg, List<Object> out) throws Exception {
out.add(msg.toString() + "\n");
}
@Override
protected void decode(C..H..Context ctx, String line, List<Object> out) throws Exception {
out.add(ChatMessage.parse(line));
}
}