소켓 통신의 기본은 접속을 받아들이는 서버와 그에 연결하는 클라이언트를 작성하는 것이다.
먼저 서버를 생각해 보자. 서버 컴퓨터에는 여러 개의 어댑터와 여러 개의 IP가 묶여 있을 수 있다.
즉, 컴퓨터와 어댑터는 1 : N 관계이고, 어댑터와 IP 주소도 1 : N 관계다.
클라이언트 소켓은 데이터가 전송돼야 할 대상을 지정하기 위해 접점 정보(IP 주소와 포트)가 필요
하다. 따라서 서버 소켓은 컴퓨터에 할당된 IP 주소 중에서 어떤 것과 연결될지 결정해야 하고 이
과정을 바인딩(binding)이라 한다. 간단히 말해서 소켓이 특정 IP와 포트에 묶이면 바인딩이 성공했
다고 볼 수 있다. 일단 이렇게 바인딩되고 나면 다른 소켓에서는 절대로 동일한 접점 정보로 바인딩
할 수 없다.
UDP 서버 소켓도 바인딩을 지원하며, 코드는 다음과 같이 작성한다.
class Program
{
static void Main(string[] args)
{
// 서버 소켓이 동작하는 스레드
Thread serverThread = new Thread(serverFunc);
serverThread.IsBackground = true;
serverThread.Start();
Thread.Sleep(500); // 소켓 서버용 스레드가 실행될 시간을 주기 위해
// 클라이언트 소켓이 동작하는 스레드
// Thread clientThread = new Thread(clientFunc);
// clientThread.IsBackground = true;
// clientThread.Start();
Console.WriteLine("종료하려면 아무 키나 누르세요...");
Console.ReadLine();
}
private static void serverFunc(object obj)
{
Socket socket = new Socket(AddressFamily.InterNetwork
, SocketType.Dgram
, ProtocolType.Udp);
IPAddress ipAddress = GetCurrentIPAddress();
if (ipAddress == null)
{
Console.WriteLine("IPv4용 랜 카드가 없습니다.");
return;
}
IPEndPoint endPoint = new IPEndPoint(ipAddress, 10200);
socket.Bind(endPoint);
}
// 현재 컴퓨터에 장착된 네트워크 어댑터의 IPv4 주소를 반환
private static IPAddress GetCurrentIPAddress()
{
IPAddress[] addrs = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
foreach (IPAddress ipAddr in addrs)
{
if (ipAddr.AddressFamily == AddressFamily.InterNetwork)
{
return ipAddr;
}
}
return null;
}
// private static void clientFunc(object obj)
// {
// // ......[클라이언트 소켓 코드 작성]......
// }
}
IP 주소를 반환하는 GetCurrentIPAddress의 코드를 좀 더 살펴보자. 현재 컴퓨터에 할당된 IPv4 주소
중에서 첫 번째 것을 반환하고 있다. 그런데 이 코드에는 분명 문제가 발생할 여지가 있다.

사용자1 컴퓨터에서 UDP 소켓 서버를 실행한다면 GetCurrentIPAddress가 10.10.10.200 또는
60.20.10.150 중 하나를 반환할 것이다. 만약 10.10.10.200을 반환 했다고 가정하면 UDP 소켓 서버는