기능
같은 네트워크 망의 두 개의 프로그램이 서로의 IP를 알 수 있다.
사용화면
설명
같은 네트워크 망에서 프로그램 두 개가 서로의 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;
}
}
}