모름

기능
 같은 네트워크 망의 두 개의 프로그램이 서로의 IP를 알 수 있다.

사용화면

(좌)IPFinder, (우)IPRespondent


설명
 같은 네트워크 망에서 프로그램 두 개가 서로의 IP를 찾고 싶을 때 사용합니다. 두 개의 프로그램에 각각 찾는 자(IPFinder), 응답하는 자(IPRespondent) 컴포넌트를 추가하고, 서로의 port를 갖게 맞춰줍니다.
 작동은 이런 순서로 됩니다. 찾는 자는 현재 네트워크망의 브로드캐스팅 주소로 응답을 요청하는 데이터를 보냅니다. 받는 자는 이 데이터를 받아서 찾는 자에게 자신의 IP를 알려주는 데이터를 보냅니다.

구성
 코드는 두 가지입니다. IPFInder.cs, IPRespondent.cs 입니다. 각 각 AddComponent 하셔서 사용하시면 됩니다. 

다운로드
 깃허브에서 받으시거나 아래 코드를 복사 붙여넣기 해서 사용하시면 됩니다.

깃허브
https://github.com/gangside/Unity_LookingForIPIfPortAreSame

코드

IPFinder.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public class IPFinder : MonoBehaviour
{
    [Header("Your Settings")] 
    [Range(49152, 65535)]
    public int port = 55555;
    public float findTimeInterval = 1;
    
    [Header("Result")]
    [SerializeField] private string findHostName;
    [SerializeField] private string findIp;
    
    private int _lastPort = 0;
    private int _sendCount = 0;
    private readonly int _initThreshold = 2;
    private readonly string _myReq;
    private readonly UdpClient _client = new UdpClient();
    
    private void Start()
    {
        StartCoroutineLoopsToFindRespondent();
    }
    
    private void StartCoroutineLoopsToFindRespondent()
    {
        StartCoroutine(CheckingLastPortAndMakeSame());
        StartCoroutine(BroadcastFindReqToEveryone());
        StartCoroutine(WaitResponse());
    }
    
    IEnumerator CheckingLastPortAndMakeSame()
    {
        while (true)
        {
            yield return null;

            if (_lastPort == port)
                continue;

            port = Mathf.Clamp(port, 49152, 65535);
            _lastPort = port;
            ClearResults();
        }
    }

    IEnumerator BroadcastFindReqToEveryone()
    {
        byte[] RequestData = Encoding.ASCII.GetBytes(Dns.GetHostName());
        while (true)
        {
            try
            {
                _client.EnableBroadcast = true;
                IPAddress[] BroadcastAddresses = GetDirectedBroadcastAddresses();
                foreach (var IPAddress in BroadcastAddresses)
                {
                    _client.Send(RequestData, RequestData.Length, new IPEndPoint(IPAddress, port));
                    
                    _sendCount++;
                    if (_sendCount > _initThreshold)
                    {
                        _sendCount = 0;
                        ClearResults();
                    }
                    
                    Debug.Log($"(1)●○ [IP Finder] broadcast [to ip:{IPAddress}]");
                }
            }
            catch (Exception e)
            {
                Debug.Log($"(-1)○○ [IP Finder] Exception: {e}");
            }

            yield return new WaitForSeconds(findTimeInterval);
        }
    }
    
    IEnumerator WaitResponse() {
        while (true) {
            if (_client.Available > 0) {
                try {
                    IPEndPoint ServerEp = new IPEndPoint(IPAddress.Any, port);
                    byte[] ServerResponseData = _client.Receive(ref ServerEp);
                    string ServerResponse = Encoding.ASCII.GetString(ServerResponseData);

                    findHostName = ServerResponse;
                    findIp = ServerEp.Address.ToString();
                    Debug.Log($"(2)●● [IP Finder] received [serverHostName:{ServerResponse}, findIp:{findIp}]");
                }
                catch (Exception e) {
                    Debug.Log($"(-1)○○ [IP Finder] Exception: {e}");
                }
            }
            yield return null;
        }
    }
    
    private void ClearResults()
    {
        findHostName = null;
        findIp = null;
    }
    
    //Get BroadcastAddresses
    private IPAddress[] GetDirectedBroadcastAddresses() {
        List<IPAddress> list = new List<IPAddress>();

        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) {
            if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback) {
                continue;
            }

            if (item.OperationalStatus != OperationalStatus.Up) {
                continue;
            }

            UnicastIPAddressInformationCollection unicasts = item.GetIPProperties().UnicastAddresses;

            foreach (UnicastIPAddressInformation unicast in unicasts) {
                IPAddress ipAddress = unicast.Address;

                if (ipAddress.AddressFamily != AddressFamily.InterNetwork) {
                    continue;
                }

                byte[] addressBytes = ipAddress.GetAddressBytes();
                byte[] subnetBytes = unicast.IPv4Mask.GetAddressBytes();

                if (addressBytes.Length != subnetBytes.Length) {
                    continue;
                }

                byte[] broadcastAddress = new byte[addressBytes.Length];
                for (int i = 0; i < broadcastAddress.Length; i++) {
                    broadcastAddress[i] = (byte)(addressBytes[i] | (subnetBytes[i] ^ 255));
                }

                list.Add(new IPAddress(broadcastAddress));
            }
        }

        return list.ToArray();
    }
}


IPRespondent.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public class IPRespondent : MonoBehaviour
{
    [Header("Settings")] 
    [Range(49152, 65535)]
    public int port = 55555;

    [Header("Requestor's Infos")] 
    [SerializeField] private string finderHostName;
    [SerializeField] private string finderIp;

    private int _lastPort = 0;
    private UdpClient _server = new UdpClient();

    private void Start()
    {
        StartCoroutineLoopsToResponse();
    }
    
    void StartCoroutineLoopsToResponse()
    {
        StartCoroutine(RestarterWhenServerPortChange());
        StartCoroutine(WaitIpFinder());
    }

    IEnumerator RestarterWhenServerPortChange()
    {
        while (true)
        {
            yield return null;

            if (_lastPort == port)
                continue;
                
            port = Mathf.Clamp(port, 49152, 65535);
            NewUdpClient();
            
            _lastPort = port;
        }
    }

    private void NewUdpClient()
    {
        try
        {
            _server.Close();
            _server = new UdpClient(port);
            Debug.Log($"(1)●○ [IPRespondent] new UdpClient (port:{port})");
        }
        catch (Exception e)
        {
            Debug.Log($"(-1)○○ [IPRespondent] Exception: {e}");
        }
    }
    
    IEnumerator WaitIpFinder() {
        yield return null;
        byte[] ResponseData = Encoding.ASCII.GetBytes(Dns.GetHostName());
        while (true)
        {
            if (_server.Available > 0 ) {
                try {
                    IPEndPoint UdpServerClientEp = new IPEndPoint(IPAddress.Any, port);
                    byte[] ClientRequestData = _server.Receive(ref UdpServerClientEp);
                    finderHostName = Encoding.ASCII.GetString(ClientRequestData);

                    finderIp = UdpServerClientEp.Address.ToString();
                    _server.Send(ResponseData, ResponseData.Length, UdpServerClientEp);
                    Debug.Log($"(2)●● [IPRespondent] received from ipFinder (ip:{UdpServerClientEp.Address}) and send myHostName)");
                }
                catch (Exception e) {
                    Debug.Log($"(-1)○○ [IPRespondent] : Exception: {e}");
                }
            }
            yield return null;
        }
    }
}