안녕하세요
이번 시간에는 네트워크 애플리케이션 프레임워크인 Netty로 간단한 WebSocket 에코 서버를 만들어보겠습니다.
1. Netty 환경 세팅
Ubuntu 20.04.6 LTS에서 실행했습니다.
Netty 프로젝트를 빌드하기 위해 Maven을 설치해보겠습니다.
Maven 란 자바 프로젝트 빌드 자동화 도구이고 Apache 소프트웨어 재단에서 관리하고 있습니다.
다음 명령어를 실행하여 maven을 설치합니다.
sudo apt update
sudo apt install maven
다음 명령어를 실행해서 잘 설치 됐는지 확인할 수 있습니다.
mvn -version
# 잘 설치됐으면 아래와 같이 출력됩니다.
# Apache Maven 3.6.3
# Maven home: /usr/share/maven
# Java version: 11.0.7, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
# Default locale: en_US, platform encoding: UTF-8
# OS name: "linux", version: "5.4.0-26-generic", arch: "amd64", family: "unix"
작업 폴더로 이동한 뒤 Git에서 Netty 웹소켓 서버 예제를 다운 받아줍니다.
git clone https://github.com/baardl/netty-websocket-server.git
프로젝트 내에 있는 Main 클래스를 실행하기 위해 설정파일에 플러그인을 추가해줘야합니다.
다운받은 폴더로 이동한뒤 pom.xml 파일에서 다음과 같이 <plugins> 태그 안에 설정을 추가합니다.
pom.xml 위치 → ( netty-websocket-server > pom.xml )
<plugins>
... 다른 플러그인 설정들 ...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>com.bardlind.ws.Main</mainClass>
</configuration>
</plugin>
</plugins>
Main 클래스 위치는 다음과 같습니다.
netty-websocket-server > src > main > java > com > bardlind > ws > Main.java
netty-websocket-server 위치에서 다음 명령어를 실행하여 빌드합니다.
mvn clean install
“BUILD SUCCESS”가 표시되면 빌드 성공입니다.
다음 명령어로 프로젝트를 실행할 수 있습니다.
mvn exec:java
이제 Main 클래스를 커스텀해서 작업을 진행할 수 있습니다.
2. WebSocket 서버 코드
Main.java
package com.bardlind.ws;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketFrameAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import java.io.File;
public class Main {
private static int PORT = 4000;
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(
new HttpServerCodec(),
new HttpObjectAggregator(65536),
new WebSocketFrameAggregator(65536),
new WebSocketServerProtocolHandler("/websocket"),
new WebSocketEchoServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = b.bind(PORT).sync();
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
WebSocketEchoServerHandler.java
package com.bardlind.ws;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.awt.*;
public class WebSocketEchoServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
// 클라이언트와 연결됐을때 실행되는 콜백함수
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}
// 클라이언트와 연결이 끊어졌을 때 실행되는 콜백함수
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("Client disconnected: " + ctx.channel().remoteAddress());
super.channelInactive(ctx);
}
// 클라이언트로부터 데이터를 전송 받았을때 실행되는 콜백함수
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
System.out.println("channelRead0: " + ctx.toString());
System.out.println("channelRead0: " + msg.text());
}
}
3. 클라이언트 코드
클라이언트 쪽 JavaScript 코드입니다.
let webSocket;
// 웹소켓 연결하는 함수
const connectWebSocketServer = () => {
webSocket = new WebSocket("ws://{네티 서버 IP주소}:4000");
// 웹소켓 이벤트 처리
// 연결 이벤트 처리
webSocket.onopen = () => {
console.log("웹소켓서버와 연결됨");
};
// 메세지 수신 이벤트 처리
webSocket.onmessage = (event) => {
console.log("서버 웹소켓에게 받은 데이터: ${event.data}");
}
// 연결 종료 이벤트 처리
webSocket.onclose = function(){
console.log("서버 웹소켓 연결 종료");
}
// 에러 발생 이벤트 처리
webSocket.onerror = function(event){
console.log(event)
}
}
// 웹소켓으로 메세지 전송하는 함수
const sendMessage = (message) => {
if(webSocket != null){
webSocket.send(message);
}
}
'Java' 카테고리의 다른 글
[JAVA] 소켓을 활용한 간단한 에코 서버와 클라이언트 (0) | 2023.10.14 |
---|---|
[JAVA] Netty에 SSL 적용하기 (0) | 2023.10.13 |
[JAVA] Swing을 이용한 스케치 기능 구현 (0) | 2023.09.12 |
[Java] awt 테트리스 모듈화 - SquareBoard (0) | 2023.08.16 |
[Java] awt 테트리스 모듈화 - Game (0) | 2023.07.26 |