Starting DotNetty server...
Server started on port 8080
Received: Hello 0
Received: Hello 1
Received: Hello 2
Received: Hello 3
Received: Hello 4

게임 개발에서 Unity와 서버 간의 원활한 통신은 매우 중요한 요소입니다. 특히 고성능의 비동기 통신 라이브러리인 DotNetty는 .NET 환경에서 이를 쉽게 구현할 수 있게 도와줍니다. 이 글에서는 DotNetty를 사용하여 Unity와 게임 서버 간의 패킷 교환 예제를 보여드리겠습니다.


DotNetty란?

DotNetty는 .NET 환경에서 사용할 수 있는 고성능 네트워크 라이브러리로, Java의 Netty를 기반으로 만들어졌습니다. 높은 확장성과 낮은 레이턴시를 제공하며, TCP 및 UDP 프로토콜을 지원합니다.

주요 특징

  • 비동기 I/O: 높은 성능과 확장성 제공.
  • 이벤트 기반 아키텍처: 네트워크 이벤트를 효율적으로 처리 가능.
  • 모듈화: 유연한 데이터 처리 파이프라인 구성.

프로젝트 설정

DotNetty를 활용하려면 NuGet 패키지를 설치해야 합니다. 다음 명령어를 통해 패키지를 추가합니다.

Install-Package DotNetty.Buffers
Install-Package DotNetty.Codecs
Install-Package DotNetty.Transport

DotNetty 서버 예제

using System;
using System.Text;
using System.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;

namespace DotNettyServer
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Starting DotNetty server...");
            var server = new GameServer();
            await server.RunAsync(8080);
        }
    }

    public class GameServer
    {
        public async Task RunAsync(int port)
        {
            var bossGroup = new MultithreadEventLoopGroup(1);
            var workerGroup = new MultithreadEventLoopGroup();

            try
            {
                var bootstrap = new ServerBootstrap();
                bootstrap.Group(bossGroup, workerGroup)
                         .Channel<TcpServerSocketChannel>()
                         .ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
                         {
                             var pipeline = channel.Pipeline;
                             pipeline.AddLast(new GameServerHandler());
                         }));

                var channel = await bootstrap.BindAsync(port);
                Console.WriteLine($"Server started on port {port}");
                await channel.CloseCompletion;
            }
            finally
            {
                await bossGroup.ShutdownGracefullyAsync();
                await workerGroup.ShutdownGracefullyAsync();
            }
        }
    }

    public class GameServerHandler : SimpleChannelInboundHandler<IByteBuffer>
    {
        protected override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg)
        {
            string receivedMessage = msg.ToString(Encoding.UTF8);
            Console.WriteLine($"Received: {receivedMessage}");

            // Echo the message back
            byte[] responseBytes = Encoding.UTF8.GetBytes($"Server response: {receivedMessage}");
            ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(responseBytes));
        }

        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Console.WriteLine($"Error: {exception.Message}");
            context.CloseAsync();
        }
    }
}
 

클라이언트 코드 (GameClient)

using System;
using System.Text;
using System.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;

namespace DotNettyClient
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Starting DotNetty client...");
            var client = new GameClient();
            await client.RunAsync("127.0.0.1", 8080);
        }
    }

    public class GameClient
    {
        public async Task RunAsync(string host, int port)
        {
            var group = new MultithreadEventLoopGroup();

            try
            {
                var bootstrap = new Bootstrap();
                bootstrap.Group(group)
                         .Channel<TcpSocketChannel>()
                         .Handler(new ActionChannelInitializer<IChannel>(channel =>
                         {
                             var pipeline = channel.Pipeline;
                             pipeline.AddLast(new GameClientHandler());
                         }));

                var channel = await bootstrap.ConnectAsync(host, port);
                Console.WriteLine("Client connected to server.");

                for (int i = 0; i < 5; i++)
                {
                    string message = $"Hello {i}";
                    byte[] messageBytes = Encoding.UTF8.GetBytes(message);
                    Console.WriteLine($"Sending: {message}");
                    await channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(messageBytes));
                    await Task.Delay(1000);
                }

                await channel.CloseAsync();
            }
            finally
            {
                await group.ShutdownGracefullyAsync();
            }
        }
    }

    public class GameClientHandler : SimpleChannelInboundHandler<IByteBuffer>
    {
        protected override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg)
        {
            string receivedMessage = msg.ToString(Encoding.UTF8);
            Console.WriteLine($"Server response: {receivedMessage}");
        }

        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Console.WriteLine($"Error: {exception.Message}");
            context.CloseAsync();
        }
    }
}

실행 방법

  1. 서버 실행: GameServer 클래스를 실행하여 서버를 시작합니다.
  2. 클라이언트 실행: GameClient 클래스를 실행하여 서버와 통신을 시작합니다.
  3. 클라이언트에서 보낸 메시지가 서버로 전달되고, 서버는 응답을 반환합니다.

실행 결과

1. 서버

Starting DotNetty server...
Server started on port 8080
Received: Hello 0
Received: Hello 1
Received: Hello 2
Received: Hello 3
Received: Hello 4

 

1. 클라이언트

Starting DotNetty client...
Client connected to server.
Sending: Hello 0
Server response: Server response: Hello 0
Sending: Hello 1
Server response: Server response: Hello 1
Sending: Hello 2
Server response: Server response: Hello 2
Sending: Hello 3
Server response: Server response: Hello 3
Sending: Hello 4
Server response: Server response: Hello 4

마무리

DotNetty는 TCP 소켓 통신에서 뛰어난 성능과 확장성을 제공하며, Unity와 같은 게임 엔진과의 통합에 적합한 라이브러리입니다. 이번 글에서는 간단한 예제를 통해 DotNetty를 사용한 서버-클라이언트 통신을 구현하는 방법을 알아보았습니다.

안녕하세요. 이번 포스트에서는 이미지 생성 API를 호출할 때 사용하는 세팅 값에 대해서 정리해보려고 합니다.

적절한 값을 세팅하면 좋은 결과를 얻을 수 있을 것 같습니다.

저는 black-forest-labs/flux-dev – Run with an API on Replicate 기준으로 정리해보고 있습니다.

* Image Generator(이미지 생성기)는 입력된 텍스트를 기반으로 인공지능이 이미지를 생성하는 도구입니다. 사용자는 간단한 설명이나 키워드를 입력하면, 이에 맞는 고품질 그래픽, 그림 또는 사진을 얻을 수 있습니다. 이 기술은 콘텐츠 제작, 디자인, 예술 등 다양한 분야에서 창의적인 작업을 돕습니다.

세팅값

prompt

생성하고자 하는 이미지의 주제를 설명하는 텍스트입니다. 예를 들어 "바닷가에 있는 빨간 등대"라고 입력하면 해당 주제의 이미지가 생성됩니다.

 

aspect_ratio

이미지를 생성 비율 ex. 1:1, 16:9

 

image

이미지를 생성할 때 참고할 초기 이미지를 제공합니다. 이 초기 이미지를 기반으로 텍스트와 결합하여 새로운 이미지를 만듭니다.

 

prompt_strength

초기 이미지와 텍스트 중 어떤 요소를 더 많이 반영할지를 설정합니다. 값이 높으면 텍스트가 더 많이 반영되고, 낮으면 초기 이미지가 더 강조됩니다.

 

num_outputs

한 번에 생성할 이미지의 개수를 지정합니다. 예를 들어 값을 3으로 설정하면 한 번에 3개의 이미지가 생성됩니다.

 

num_inference_steps

이미지 생성 과정에서 품질과 세부 사항을 결정하는 반복 단계 수입니다. 단계가 많을수록 이미지 품질이 높아지지만, 처리 시간이 더 길어집니다.

 

guidance

텍스트 지침을 얼마나 엄격하게 따를지를 조정하는 값입니다. 높을수록 텍스트 설명에 더 충실한 이미지가 생성됩니다.

 

seed

생성 결과를 반복적으로 동일하게 얻기 위한 랜덤 값 초기화 번호입니다. 같은 prompt와 seed를 사용하면 동일한 이미지를 생성할 수 있습니다.

 

output_format

생성된 이미지의 파일 형식을 설정합니다. 예를 들어 PNG 또는 JPEG 같은 형식을 선택할 수 있습니다.

 

output_quality

생성 이미지의 해상도와 품질을 조정하는 옵션입니다. 값이 높을수록 선명한 이미지가 만들어지지만 파일 크기가 커질 수 있습니다.

 

disable_safety_checker

안전 필터를 비활성화할지 여부를 설정합니다. 비활성화하면 특정 제한 없이 다양한 이미지가 생성될 수 있습니다.

 

go_fast

이미지 품질을 조금 낮추는 대신 생성 속도를 빠르게 하는 옵션입니다. 시간이 제한된 상황에서 유용합니다.

 

megapixels

생성 이미지의 크기(해상도)를 결정하는 값입니다. 예를 들어 1MP는 작은 크기, 5MP는 고해상도 이미지를 의미합니다.

결론

이미지 생성 API의 세팅 값은 각 항목이 이미지의 품질, 속도, 스타일에 영향을 미치므로 목적에 맞게 조정해야 합니다. 처음에는 기본 값을 사용해보고, 필요에 따라 세부 옵션을 조정하며 최적의 결과를 찾아가는 것이 중요합니다. 이러한 설정을 이해하면 원하는 이미지를 효율적으로 생성할 수 있습니다.

react 실행을 했을 때 해당 오류를 볼 수 있습니다.

 

1. npm 재설치

npm cache clean --force
rm node_modules
npm install

혹은

npm update
node_modules 폴더 삭제
package-lock.json 삭제
npm cache clean --force
npm install

https://nitpick92.tistory.com/17

 

[linux] centos nginx Reverse-Proxy 서버 만들기

https://nitpick92.tistory.com/11 [linux] centos7 yum nginx 삭제 및 설치 방법 centos 7 환경에서 nginx 삭제 후 재설치하는 방법에 대해서 알아보려고 합니다. 1. nginx 삭제 # 설치 여부 확인 yum list installed nginx # 삭

nitpick92.tistory.com

지난 시간에는 nginx를 Reverse-Proxy 서버로 사용하는 법을 알아보았습니다.

이어서 하나의 서버에서 여러 도메인을 관리할 수 있는 방법을 알아보겠습니다.

 

nginx multi port

1. nginx conf 파일 수정

# server1
server {
      # 들어오는 port
      listen       8080;
      server_name  localhost;

      error_page   500 502 503 504  /50x.html;
      location = /50x.html {
          root   /usr/share/nginx/html;
      }

      # 실제로 바라볼 port
      location / {
        proxy_pass http://127.0.0.1:9090;
      }
}

# server2
server {
      # 들어오는 port
      listen       8081;
      server_name  localhost;

      error_page   500 502 503 504  /50x.html;
      location = /50x.html {
          root   /usr/share/nginx/html;
      }

      # 실제로 바라볼 port
      location / {
        proxy_pass http://127.0.0.1:9091;
      }
}

2. nginx 서버를 재시작 해줍니다.

sudo systemctl restart nginx

+ Recent posts