본문 바로가기
💻 programming/unity

유니티 UDP 소켓 통신 구현하기 - C++ UDP 클라이언트 예제 코드 <4>

by 연구원-A 2023. 1. 13.
반응형

[이전 포스팅]

2023.01.13 - [programming] - 유니티 UDP 소켓 통신 구현하기 - 예제 프로젝트 소개 <1>

2023.01.13 - [programming] - 유니티 UDP 소켓 통신 구현하기 - 유니티 UDP 서버 C# 예제 코드 <2>

2023.01.13 - [programming] - 유니티 UDP 소켓 통신 구현하기 - 파이썬 UDP 클라이언트 예제 코드 <3>

 

우리가 소켓 통신을 하는 이유는 특정 개발 언어와 관계없이 네트워크를 통해 데이터를 주고 받을 수 있기 때문이다

마지막으로 파이썬에 이어서 C++ UDP 클라이언트를 구현해보고 동작을 확인해보았다

 

main 코드

TransferManager 클래스에 UDP IP 주소와 포트번호를 전달하여 인스턴스를 생성한다

키보드로부터 입력을 받아서 direction 문자열을 생성한다

생성된 direction 문자열을 TransferManager.SendData 함수에 전달하여 UDP로 데이터를 전달한다

#include <iostream>
#include <string>
#include <thread>
#include <chrono>

#include "transfer_manager.h"

using namespace std;

std::string get_direction(const int& dir) {
    std::string ret = "";
    switch(dir) {
        case 0:
            ret = "up";
            break;
        case 1:
            ret = "down";
            break;
        case 2:
            ret = "left";
            break;
        case 3:
            ret = "right";
            break;
        default:
            break;
    }
    return ret;
}

int main() {
    std::cout << "hello world" << std::endl;

    auto transfer_manager_ = std::make_unique<TransferManager>("127.0.0.1", 50002);
    transfer_manager_->Initialize();

    while(true) {
        int direction = -1;
        std::cout << "Enter direction (0:up, 1:down, 2:left, 3:right): ";
        std::cin >> direction;

        if(direction >= 0 && direction <= 3) {
            auto direction_str = get_direction(direction);
            transfer_manager_->SendData(direction_str);
        } else {
            std::cout <<"Direction must be included between 0 and 3 : " << direction << std::endl;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

 

TransferManager.h 헤더파일

#ifndef _TRANSFER_MANAGER_H_
#define _TRANSFER_MANAGER_H_

#include <iostream>
#include <vector>
#include <string>
#include <cstring>

// rapidjson
#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>

#include <arpa/inet.h>
#include <sys/socket.h>

class TransferManager {
 public:
    TransferManager(std::string ip_addr, int port) : ip_addr_(ip_addr), port_(port) {}
    virtual ~TransferManager() = default;

    void Initialize();
    void SendData(const std::string& direction);
    void Shutdown();

 private:
    int sock_;
    struct sockaddr_in serv_addr_;
    std::string ip_addr_ = "";
    int port_ = 0;
};

#endif

 

TransferManager.cc

Initialize() 함수에서 UDP 클라이언트 소켓을 생성한다

SendData(const std::string& direction) 함수에서 JSON 문자열을 생성한뒤 소켓을 통해 전송한다

#include "transfer_manager.h"
#include <iostream>
#include <ctime>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>

void TransferManager::Initialize() {
    sock_ = socket(AF_INET, SOCK_DGRAM, 0);
    memset(&serv_addr_, 0, sizeof(serv_addr_));
    serv_addr_.sin_family=AF_INET;
    serv_addr_.sin_addr.s_addr=inet_addr(ip_addr_.c_str());
    serv_addr_.sin_port=htons(port_);
}

void TransferManager::SendData(const std::string& direction) {
    char message[65535];

    rapidjson::Document document;
    document.SetObject();
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

    rapidjson::Value str_direction;
    str_direction.SetString(direction.c_str(), direction.length(), allocator);

    document.AddMember("direction", str_direction, allocator);
    rapidjson::StringBuffer strbuf;
    rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
    document.Accept(writer);

    std::string ret = strbuf.GetString();

    std::cout << ret << std::endl;
    ret.copy(message, strlen(ret.c_str()));

    int perr = sendto(sock_, message, strlen(ret.c_str()), 0, (sockaddr*)&serv_addr_, sizeof(serv_addr_));
    if (perr < 0) {
        std::cout << "failed to send data to UDP server" << std::endl;
    }
}

void TransferManager::Shutdown() {

}

 

컴파일하기

CMakeLists.txt 파일을 작성한다

cmake_minimum_required(VERSION 2.4)
PROJECT(client-cpp)

FILE(GLOB_RECURSE SRC_FILES src/*.c*)
FILE(GLOB_RECURSE HDR_FILES src/*.h*)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)

add_executable(${PROJECT_NAME} ${HDR_FILES} ${SRC_FILES})
add_definitions(-std=c++14)

install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})

터미널에서 cmake 명령어를 통해 빌드한다

mkdir -p build

pushd build
  cmake ..
  make -j2
popd

 

실행하기

build 폴더에 생성된 client-cpp 바이너리를 실행한다

cd build
./client-cpp

 

⭐ Python 스크립트와 마찬가지로 JSON 문자열을 만들어 전송하는 C++ 코드를 작성하여 보았다

⭐ 유니티 UDP 서버를 플레이하고 C++ 바이너리를 실행하면 키보드 입력에 따라

⭐ Sphere 오브젝트가 이동하는 것을 확인할 수 있다

 

전체 파일을 아래 repository에 업로드해두었다

https://github.com/taemin-hwang/study-space/tree/master/unity/01_udp/03-client-cpp

 

GitHub - taemin-hwang/study-space

Contribute to taemin-hwang/study-space development by creating an account on GitHub.

github.com

 

마치며

UDP 서버를 유니티에서 C#으로,

UDP 클라이언트를 파이썬과 C++으로 각각 구현해보았다

 

UDP 클라이언트로 부터 수신한 데이터를 이용해 유니티 게임 오브젝트를 이동시켜 보면서 데이터 송수신을 검증하였다

 

최대한 간단한 코드로 작성해보려고 했는데 많은 도움이 되었길 바라며 포스팅은 여기서 끝

반응형

댓글