ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 json(JsonUtility) 송신 => c++서버 json 수신
    프로그래밍/의문 2016. 3. 29. 14:33
    반응형

    Json Utility는 유니티 5.3 버전에서의 추가된 사항으로, 유니티에서 직접 제공하는 json 라이브러리입니다.

    외부 라이브러리를 사용하지 않고도 json 작성을 가능하게 합니다.


    이전 버전에서 json을 사용하려면 외부 라이브러리를 썼다고 하는데 기기에 따라 호환이 안 되는 경우가 많아,

    게임 하나에 json 라이브러리만 2개 이상인 경우도 많았다고 합니다.



    #클라이언트 사이드

    - 유니티 5.3버전 JsonUtility 사용


    #서버 사이드

    - boost/property_tree/json_parser 사용



    #유니티 클라이언트 코드


    0) 프로토콜 정의

    1
    2
    3
    4
    5
    6
    7
    8
        namespace Json
        {
            public class ReqLogin
            {
                public string id;
                public string pw;
            }
        }
    cs



    1) 송신 부분

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class LoginSceneInput : MonoBehaviour {
     
        public InputField idField; // id 입력 필드
        public InputField pwField; // pw 입력 필드
     
        // 버튼이 눌렸을 때 호출되는 함수
        public void TryLogin()
        {
            // id와 pw 필드에서 텍스트를 가져옴
            var id = idField.text;
            var pw = pwField.text;
     
            // 패킷의 id와 pw 값 설정
            var packet = new Protocols.Json.ReqLogin();
            packet.id = id;
            packet.pw = pw;
     
            // 구조체를 json 포맷으로 변환
            var packetJson = JsonUtility.ToJson(packet);
     
            try
            {
                // 서버로 송신
                var arr = System.Text.Encoding.UTF8.GetBytes(packetJson);
                NetworkSession.Instance.SendPacket(arr, arr.Length);
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
                return;
            }
        }
    }

    cs


    # c++ 서버 코드


    0) 수신 부분

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      virtual void received(receive_buffer& buf) override
      {
        using ptree = boost::property_tree::ptree;
        namespace json = boost::property_tree::json_parser;
     
        boost::asio::streambuf sb;
        sb.sputn(buf.data<char*>(), buf.size());
     
        std::istream is{ &sb };
     
        // json을 읽는다.
        ptree pt;
     
        json::read_json(is, pt); 
        
        auto idval = pt.get<std::string>("id"); // id 필드에서 값을 가져옴
        auto pwval = pt.get<std::string>("pw"); // pw 필드에서 값을 가져옴
      }

    cs



    # 결과 확인


    0) 유니티 클라이언트


    1) c++ 서버




    # + 바이너리 헤더 붙이기


    바이트 배열로 [헤더][json 데이터] 구조를 만드는 방법. 헤더에는 json 데이터의 길이와 타입이 담긴다.


    0) 헤더 정의

    1
    2
    3
    4
    5
    6
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public class Header
        {
            public Types type; // 2
            public Int32 size; // 4
        }

    cs



    1) json 데이터와 헤더를 합쳐서 바이트 배열을 만드는 함수

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
            public static byte[] MakeBytesPacket(Protocols.Types type, object data)
            {
                // 헤더를 만든다.
                var header = new Protocols.Header();
                var headerSize = Marshal.SizeOf(header);
     
                // 데이터를 json 포맷으로
                var jsonData = Encoding.UTF8.GetBytes(JsonUtility.ToJson(data));
     
                header.type = type;
                header.size = jsonData.Length;
     
                // 버퍼 할당(헤더 크기 + json데이터 크기)
                byte[] buffer = new byte[headerSize + jsonData.Length];
     
                // 헤더 포인터 할당
                IntPtr headerPtr = Marshal.AllocHGlobal(headerSize);
     
                // 헤더클래스를 구조체로 변환
                Marshal.StructureToPtr(header, headerPtr, true);
     
                // 버퍼에 헤더 복사
                Marshal.Copy(headerPtr, buffer, 0, headerSize);
     
                // 헤더 포인터 삭제
                Marshal.FreeHGlobal(headerPtr);
     
                // 버퍼에 json 데이터 복사
                Buffer.BlockCopy(
                    jsonData,
                    0,
                    buffer,
                    headerSize, // 헤더 이후부터 복사
                    jsonData.Length);
     
                return buffer;
            }

    cs


    반응형
Designed by Tistory.