Netty Socket Server
이전 포스팅에서 NIO, NETTY 개념을 잡아보았으니 이를 간단한 코드 3개로 테스트 겸? 실습 해보았다.
Channel Pipeline Handler
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// Client로부터 데이터를 수신받으면 Echo 출력하는 Method
ByteBuf in = (ByteBuf)msg;
// print received message
System.out.println("Server Received : " + in.toString(CharsetUtil.UTF_8));
ctx.write(in);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// Channel에서 Read한 후 Buffer 비우는 Method
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// Exception 관련 Method
cause.printStackTrace();
ctx.close();
}
}
Server Main
public class ServerMain {
private final int port;
public ServerMain(int port) {
this.port = port;
}
public static void main(String[] args) {
if(args[0] == null) {
args[0] = "4000";
}
ServerMain server = new ServerMain(Integer.parseInt(args[0]));
try {
// socket server start
Thread.sleep(5000);
server.start();
}
catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
}
private void start() throws Exception {
System.out.println("Start Netty Socket Server");
final EchoServerHandler handler = new EchoServerHandler();
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap sb = new ServerBootstrap();
sb.group(group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("CHANNEL OPEN");
ch.pipeline().addLast(handler);
}
});
ChannelFuture cf = sb.bind().sync();
cf.channel().closeFuture().sync();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
group.shutdownGracefully().sync();
}
}
}
Socket Client
Client도 똑같이 Java로 하려다가, 조금 특이하게 C++
로도 Socket 통신을 해보고싶어 Client는 C++로 제작해보았다.
C++은 Win32 계열 Socket을 사용했는데 이 Header가 상당히 로우레벨인 듯 하여 나의 마니악한 호기심을 자극한다.
그러나 이번엔 Netty SocketServer가 데이터를 잘 받는지만 확인하면 되니 가장 기본적인 설정만 잡았다.
#pragma once
#include "pch.h"
#include <WinSock2.h>
#include <iostream>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)
using namespace std;
void ErrorHandling(std::string msg) {
cout << msg << endl;
exit(1);
}
int main(int argc, char** argv) {
cout << "==== C++ Socket Client Start ====\n\n";
int PORT = 4000;
WSADATA ws;
SOCKET sc;
SOCKADDR_IN servaddr;
char msg[1024];
int len;
if (WSAStartup(MAKEWORD(2, 2), &ws) != 0)
ErrorHandling("WSAStartup Error\n");
// Create New Socket
sc = socket(PF_INET, SOCK_STREAM, 0);
if (sc == INVALID_SOCKET)
ErrorHandling("Socket Error\n");
// New Socket Configuration
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
cout << "socket connection config : OK\n";
if (connect(sc, (LPSOCKADDR)&servaddr, sizeof(servaddr)) == SOCKET_ERROR) {
ErrorHandling("Connection Error\n");
}
while (1) {
char msg[1024];
fputs("Enter message : ", stdout);
fgets(msg, 1024, stdin);
if (!strcmp(msg, "q\n")) {
break;
}
send(sc, msg, strlen(msg), 0);
cout << "i sent message : " << msg << '\n';
}
return 0;
}
Written on January 8, 2021