[C# – 기초 강좌] 9-2. 통신(Communication) – Socket

Socket Communication은 컴퓨터 네트워크에서 두 프로세스 간에 데이터를 주고받기 위한 엔드포인트를 제공하는 메커니즘입니다. Socket은 IP 주소와 포트 번호를 결합하여 하나의 네트워크에서 두 장치가 서로 통신할 수 있게 합니다.

Socket Communication이란?

개요

Socket 통신은 네트워크 프로그래밍의 핵심 요소로, 클라이언트-서버 모델에서 주로 사용됩니다.

클라이언트는 서버에 연결을 요청하고, 서버는 클라이언트의 요청을 받아들이거나 거부할 수 있습니다.

이 연결을 통해 데이터를 주고받는 것이 Socket 통신의 기본 원리입니다.

OSI 7 Layer 모델

Socket 통신은 네트워크 프로그래밍의 핵심 요소로, 컴퓨터 네트워크 상에서 두 프로세스가 데이터를 주고받기 위한 엔드포인트를 제공합니다.

이를 이해하기 위해 OSI(Open Systems Interconnection) 7 Layer 모델을 통해 더 자세히 알아보겠습니다.

OSI 7 Layer 모델은 네트워크 통신을 일곱 개의 계층으로 나누어 설명하는 모델입니다. 각 계층은 특정한 네트워크 기능을 담당하며, 서로 독립적으로 설계되었습니다.

  1. 물리 계층 (Physical Layer): 데이터 전송을 위한 물리적인 매체를 정의합니다. 예를 들어, 케이블, 라우터 등의 하드웨어가 포함됩니다.
  2. 데이터 링크 계층 (Data Link Layer): 물리 계층을 통해 데이터를 전송하고 오류 검출 및 수정 기능을 제공합니다. 예를 들어, 이더넷, 스위치가 포함됩니다.
  3. 네트워크 계층 (Network Layer): 데이터를 목적지까지 경로 설정 및 전송합니다. IP 주소를 이용한 라우팅 기능을 담당합니다.
  4. 전송 계층 (Transport Layer): 데이터 전송의 신뢰성을 보장합니다. TCP, UDP 프로토콜이 이 계층에 속합니다.
  5. 세션 계층 (Session Layer): 통신 세션을 설정, 유지 및 종료합니다.
  6. 표현 계층 (Presentation Layer): 데이터 형식 변환, 압축, 암호화 등의 기능을 제공합니다.
  7. 응용 계층 (Application Layer): 사용자와 직접 상호작용하는 애플리케이션을 제공합니다. HTTP, FTP, SMTP 등이 이 계층에 속합니다.
OSI 7 Layer
출처: https://www.bmc.com/blogs/osi-model-7-layers/

Protocol 종류

Protocol 종류로 일반적으로 TCP/IP와 UDP를 선택하여 사용합니다. 이는 보통 속도와 신뢰성을 위한 부분에서 필요에 따라 선택적으로 사용합니다.

1. TCP (Transmission Control Protocol)
  • 특징:
    • 연결 지향적 프로토콜로, 신뢰성 있는 데이터 전송을 보장합니다.
    • 데이터는 순서대로 전송되며, 손실된 데이터는 재전송됩니다.
  • 장점:
    • 데이터 무결성을 보장하며, 흐름 제어와 혼잡 제어 기능을 제공합니다.
    • 패킷이 순서대로 도착합니다.
  • 단점:
    • 연결 설정과 해제 과정에서 오버헤드가 발생하며, 데이터 전송 속도가 상대적으로 느립니다.
  • 사용 예:
    • 웹 브라우징(HTTP/HTTPS), 이메일(SMTP, IMAP, POP3), 파일 전송(FTP)
2. UDP (User Datagram Protocol)
  • 특징:
    • 비연결 지향적 프로토콜로, 빠르고 간단한 데이터 전송을 제공합니다.
    • 데이터그램은 독립적으로 전송됩니다.
  • 장점:
    • 연결 설정이 필요 없고, 오버헤드가 적으며 빠른 데이터 전송이 가능합니다.
    • 브로드캐스트와 멀티캐스트를 지원합니다.
  • 단점:
    • 데이터 전송의 신뢰성을 보장하지 않으며, 데이터 순서 보장이 없습니다.
    • 데이터 손실이 발생할 수 있습니다.
  • 사용 예:
    • 실시간 스트리밍, 온라인 게임, VoIP(Voice over IP)
3. ICMP (Internet Control Message Protocol)
  • 특징:
    • 네트워크 상태 및 오류 메시지를 전달하는 데 사용되는 프로토콜입니다.
    • 주로 네트워크 진단 및 관리 용도로 사용됩니다.
  • 장점:
    • 네트워크 문제를 탐지하고 진단하는 데 유용합니다.
    • 패킷 손실 및 지연을 분석할 수 있습니다.
  • 단점:
    • 데이터 전송을 목적으로 하지 않으며, 주로 네트워크 상태 정보를 전달하는 데 사용됩니다.
  • 사용 예:
    • 핑(Ping), 트레이서트(Traceroute)
4. SCTP (Stream Control Transmission Protocol)
  • 특징:
    • 연결 지향적 프로토콜로, 다중 스트림과 다중 호밍 기능을 지원합니다.
    • TCP와 UDP의 장점을 결합한 프로토콜입니다.
  • 장점:
    • 다중 스트림을 통해 데이터가 병렬로 전송되며, 하나의 연결에 여러 IP 주소를 사용할 수 있습니다.
    • 데이터 순서 보장과 신뢰성 있는 전송을 제공합니다.
  • 단점:
    • 복잡성이 높으며, 모든 네트워크 환경에서 지원되지 않을 수 있습니다.
  • 사용 예:
    • 전송 제어 프로토콜, 통신 네트워크(VoIP 등)

C#에서 Socket 통신 사용하기

주요 네임스페이스(NameSpace)

  • System.Net: 네트워킹 기능을 제공하는 네임스페이스입니다. IP 주소와 같은 네트워크 정보를 다룹니다.
  • System.Net.Sockets: 소켓을 이용한 네트워크 통신 기능을 제공하는 네임스페이스입니다.

주요 클래스(Class)

  1. IPAddress: IP 주소를 나타내는 클래스입니다.
    • Parse(string ipString): 문자열 형식의 IP 주소를 IPAddress 객체로 변환합니다.
  2. IPEndPoint: 네트워크 엔드포인트를 나타내는 클래스입니다. IP 주소와 포트 번호를 결합하여 생성됩니다.
    • IPEndPoint(IPAddress address, int port): IP 주소와 포트를 사용하여 IPEndPoint 인스턴스를 초기화합니다.
  3. Socket: 소켓을 생성하고 관리하는 클래스입니다. 클라이언트와 서버 간의 연결을 설정하고 데이터를 송수신할 수 있습니다.
    • Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType): 소켓을 초기화합니다.
    • Bind(EndPoint localEP): 소켓을 로컬 엔드포인트에 바인딩합니다.
    • Listen(int backlog): 들어오는 연결을 대기 상태로 만듭니다.
    • Accept(): 대기 중인 연결을 수락합니다.
    • Connect(EndPoint remoteEP): 원격 호스트에 연결을 시도합니다.
    • Send(byte[] buffer): 데이터를 송신합니다.
    • Receive(byte[] buffer): 데이터를 수신합니다.
    • Shutdown(SocketShutdown how): 소켓의 송수신을 중지합니다.
    • Close(): 소켓을 닫습니다.
  4. Encoding: 문자열을 바이트 배열로 변환하거나 바이트 배열을 문자열로 변환하는 데 사용됩니다.
    • ASCII: ASCII 인코딩을 사용합니다.
    • GetBytes(string s): 문자열을 바이트 배열로 변환합니다.
    • GetString(byte[] bytes, int index, int count): 바이트 배열을 문자열로 변환합니다.

Socket 종류

1. 스트림 소켓 (Stream Socket)
  • 특징: 연결 지향적(연결 기반) 소켓으로, TCP(Transmission Control Protocol)를 사용합니다. 데이터를 신뢰성 있게 전송하고 수신합니다.
  • 장점: 데이터가 순서대로 전달되고, 데이터 손실이 거의 없습니다. 연결 상태를 유지하기 때문에 안정적인 통신이 가능합니다.
  • 단점: 연결 설정과 해제에 추가적인 오버헤드가 발생합니다.
  • 사용 예: 웹 브라우징, 이메일 전송, 파일 전송 등
2. 데이터그램 소켓 (Datagram Socket)
  • 특징: 비연결 지향적(비연결 기반) 소켓으로, UDP(User Datagram Protocol)를 사용합니다. 데이터를 독립적인 패킷으로 전송합니다.
  • 장점: 연결 설정 없이 데이터를 전송할 수 있어 빠릅니다. 오버헤드가 적고, 브로드캐스트와 멀티캐스트에 적합합니다.
  • 단점: 데이터가 순서대로 도착하지 않을 수 있으며, 데이터 손실이 발생할 수 있습니다.
  • 사용 예: 실시간 스트리밍, 온라인 게임, VoIP(Voice over IP) 등
3. 원시 소켓 (Raw Socket)
  • 특징: IP 계층의 헤더 정보를 직접 다룰 수 있는 소켓으로, TCP나 UDP와 같은 전송 계층 프로토콜을 직접 다룰 수 있습니다.
  • 장점: 네트워크 프로토콜의 모든 세부 정보를 제어할 수 있습니다. 맞춤형 프로토콜을 구현하거나 네트워크 패킷을 분석할 때 유용합니다.
  • 단점: 프로그래밍이 복잡하며, 잘못된 구현은 네트워크에 문제를 일으킬 수 있습니다. 일반적으로 관리자 권한이 필요합니다.
  • 사용 예: 네트워크 모니터링, 침입 탐지 시스템, 네트워크 프로토콜 분석 등

기본 동작 순서

  1. 서버 소켓을 설정하고 클라이언트 연결을 기다립니다. (Bind, Listen)
  2. 클라이언트가 서버에 연결을 시도합니다. (Connect)
  3. 클라이언트와 서버 간에 데이터를 주고받습니다. (Send, Receive)
  4. 연결을 종료합니다. (Shutdown, Close)
socket communication process
출처: https://nowonbun.tistory.com/155

예제

예제는 TCP/IP를 사용한 예제를 작성하였습니다.

Socket Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SocketServer
{
    class Program
    {
        static void Main()
        {
            // Set the IP address and port
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            int port = 8080;
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket
            Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                // Bind the socket to the local endpoint and listen for incoming connections
                listener.Bind(localEndPoint);
                listener.Listen(10); // 10 is the maximum length of the pending connections queue

                Console.WriteLine("Start Server. Waiting for a connection...");

                // Accept the connection
                Socket handler = listener.Accept();
                string data = null;
                byte[] bytes = new byte[1024]; // Data buffer

                // Receive the data
                int bytesRec = handler.Receive(bytes); // The number of bytes received
                data += Encoding.ASCII.GetString(bytes, 0, bytesRec); // Convert bytes to string
                Console.WriteLine("Receive Data: {0}", data);

                // Send response to the client
                byte[] msg = Encoding.ASCII.GetBytes("Received your message.");
                handler.Send(msg);

                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("Close the server.");
        }
    }
}
Socket Client
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;

namespace HelloWorld
{
    class Program
    {
        static void Main()
        {
            // Set the IP address and port
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            int port = 8080;
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket
            Socket sender = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                // Try to connect to the server
                sender.Connect(remoteEP);
                Console.WriteLine("Successfully connected to {0}", sender.RemoteEndPoint);

                // Send message to the server
                string message = "Hello Server!";
                byte[] msg = Encoding.ASCII.GetBytes(message);
                int bytesSent = sender.Send(msg);

                // Receive response from the server
                byte[] bytes = new byte[1024];
                int bytesRec = sender.Receive(bytes);
                Console.WriteLine("Res receive: {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));

                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

                // Wait
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("Close the client.");
        }
    }
}
결과
Socket Communication Result (TCP/IP)

참고 링크

Leave a Comment