본문 바로가기

프로그램/유니티 네트워크

[유니티 네트워크] 비동기 UdpSender, UdpReceiver 클래스 전송 (UdpClient)

728x90
반응형

1. 내용

 (1) 권장 포트 번호 : 49152 ~ 65535

 

포트 번호

내용

0

사용하지 않음.

1 ~1023

잘 알려진 포트(Well-known port)

1024 ~ 49151

등록된 포트(Registered port)

49152 ~ 65535

동적 포트(Dynamic port)

 

 (2) 전송 패키지 사이즈

 Udp는 이론상으로는 65507 byte까지 보낼수 있지만, 내부 통신이 아닌 경우 1024 byte이내를 권장합니다.

 

 (3) 소스 내용

  - 유니티와 유니티, 또는 C#과의 통신

  - 클래스 : UdpClient

  - 개체 직렬화 : 직렬화(Serialization) 역직렬화(Deserialization)

  - 전송 패킷 : 클래스 ↔ 바이트 배열

 

2. 소스

2.1 Receiver.cs

using UnityEngine;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

public class Receiver : MonoBehaviour
{
    private UdpClient m_Receiver;
    public int m_Port = 50001;
    public Packet m_ReceivedPacket = new Packet();

    void Awake()
    {
        InitReceiver();
    }

    void OnApplicationQuit()
    {
        CloseReceiver();
    }

    void InitReceiver()
    {
        try
        {
            if (m_Receiver == null)
            {
                m_Receiver = new UdpClient(m_Port);
                m_Receiver.BeginReceive(new AsyncCallback(DoReceiveCallback), null);
            }
        }
        catch (SocketException e)
        {
            Debug.Log(e.Message);
        }
    }

    void DoReceiveCallback(IAsyncResult ar)
    {
        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, m_Port);
        byte[] m_ReceivedBytes;

        if (m_Receiver != null)
        {
            m_ReceivedBytes = m_Receiver.EndReceive(ar, ref ipEndPoint);
        }

        else
        {
            return;
        }

        m_Receiver.BeginReceive(new AsyncCallback(DoReceiveCallback), null);

        m_ReceivedPacket = Deserialize(m_ReceivedBytes);
        DoReceivePacket();
    }

    // 받은 값 처리 ...
    void DoReceivePacket()
    {
        Debug.LogFormat($"BoolVariable = {m_ReceivedPacket.m_BoolVariable} " +
            $"IntlVariable = {m_ReceivedPacket.m_IntlVariable} " +
            $"FloatlVariable = {m_ReceivedPacket.m_FloatlVariable} " +
            $"StringlVariable = {m_ReceivedPacket.m_StringlVariable}");
        // 출력 : BoolVariable = True IntlVariable = 1 FloatlVariable = 32.06327 StringlVariable = CoderZero 코드제로
    }

    void CloseReceiver()
    {
        if (m_Receiver != null)
        {
            m_Receiver.Close();
            m_Receiver = null;
        }
    }

    Packet Deserialize(byte[] bytes)
    {
        MemoryStream stream = new MemoryStream(bytes);
        BinaryFormatter formatter = new BinaryFormatter();

        Packet packet = new Packet();
        packet.m_BoolVariable = (bool)formatter.Deserialize(stream);
        packet.m_IntlVariable = (int)formatter.Deserialize(stream);
        packet.m_FloatlVariable = (float)formatter.Deserialize(stream);
        packet.m_StringlVariable = (string)formatter.Deserialize(stream);

        return packet;
    }
}

 

 

2.2 Sender.cs

using UnityEngine;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

public class Sender : MonoBehaviour
{
    private UdpClient m_Sender = new UdpClient();
    public string m_ReceiverIp = "127.0.0.1";
    public int m_Port = 50001;
    public Packet m_SendPacket = new Packet();
    private byte[] m_SendBytes;

    void Start()
    {
        InitSender();
    }

    void Update()
    {
        SetSendPacket();
        DoBeginSend(m_SendBytes);
    }

    void OnApplicationQuit()
    {
        CloseSender();
    }

    void InitSender()
    {
        m_Sender.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        m_Sender.Connect(IPAddress.Parse(m_ReceiverIp), m_Port);
    }

    // 보내는 값
    void SetSendPacket()
    {
        m_SendPacket.m_BoolVariable = !m_SendPacket.m_BoolVariable;
        m_SendPacket.m_IntlVariable++;
        if (m_SendPacket.m_IntlVariable >= int.MaxValue - 1)
            m_SendPacket.m_IntlVariable = default(int);

        m_SendPacket.m_FloatlVariable = UnityEngine.Random.Range(0f, 100.0f);
        m_SendPacket.m_StringlVariable = "CoderZero 코더제로";

        m_SendBytes = Serialize(m_SendPacket);
    }

    void DoBeginSend(byte[] packets)
    {
        m_Sender.BeginSend(packets, packets.Length, new AsyncCallback(SendCallback), m_Sender);
    }

    void SendCallback(IAsyncResult ar)
    {
        UdpClient udpClient = (UdpClient)ar.AsyncState;
    }

    void CloseSender()
    {
        if (m_Sender != null)
        {
            m_Sender.Close();
            m_Sender = null;
        }
    }

    byte[] Serialize(Packet packet)
    {
        MemoryStream memoryStream = new MemoryStream();
        BinaryFormatter binaryFormatter = new BinaryFormatter();

        binaryFormatter.Serialize(memoryStream, packet.m_BoolVariable);
        binaryFormatter.Serialize(memoryStream, packet.m_IntlVariable);
        binaryFormatter.Serialize(memoryStream, packet.m_FloatlVariable);
        binaryFormatter.Serialize(memoryStream, packet.m_StringlVariable);

        return memoryStream.ToArray();
    }
}

 

2.3 Packets.cs

using System;

[Serializable]
public class Packet
{
    public bool m_BoolVariable;
    public int m_IntlVariable;
    public float m_FloatlVariable;
    public string m_StringlVariable;
}

 

728x90
반응형