프로그래밍/C#

C#에서 네트워킹 소켓 이해하기: 기초부터 고급까지

shimdh 2025. 9. 17. 20:11
728x90

컴퓨터 네트워킹의 핵심 개념인 소켓은 네트워크를 통해 서로 다른 프로세스 간의 통신을 가능하게 합니다. 특히 C#을 사용하여 로컬 네트워크나 인터넷을 통해 데이터 전송이 필요한 애플리케이션을 개발할 때 소켓을 이해하는 것은 필수적입니다. 이번 포스트에서는 소켓의 기본 개념부터 C#에서의 실용적인 구현 방법까지 자세히 살펴보겠습니다.

소켓이란 무엇인가?

소켓은 컴퓨터 네트워크를 통해 데이터를 송수신하기 위한 끝점입니다. TCP(전송 제어 프로토콜)와 UDP(사용자 데이터그램 프로토콜)와 같은 프로토콜을 사용하여 다른 컴퓨터와 통신할 수 있는 방법을 제공합니다.

TCP와 UDP의 차이점

  • TCP: 연결 지향 프로토콜로, 메시지가 전송된 순서대로 신뢰성 있게 전달되도록 보장합니다.
  • UDP: 연결 없는 프로토콜로, 신뢰성이나 순서를 보장하지 않고 더 빠른 메시지 전달을 허용합니다.

소켓의 작동 원리

  1. 소켓 생성: 주소 패밀리(IPv4 또는 IPv6), 소켓 유형(스트림 또는 데이터그램), 프로토콜 유형을 지정하여 소켓을 생성합니다.
  2. 바인딩: 서버 측 애플리케이션의 경우, 소켓을 IP 주소와 포트 번호에 바인딩하여 들어오는 연결을 수신할 수 있도록 합니다.
  3. 리스닝: 서버는 바인딩된 포트에서 클라이언트 요청을 수신 대기합니다.
  4. 연결 수락: 클라이언트가 연결되면, 서버는 이 연결을 수락하고 전용 통신 채널을 설정합니다.
  5. 데이터 전송: Send()Receive()와 같은 메서드를 사용하여 이 설정된 연결을 통해 데이터를 송수신할 수 있습니다.
  6. 연결 종료: 통신이 완료되면, 양측은 각각의 소켓을 닫아 리소스를 해제해야 합니다.
728x90

C#에서의 실용적인 예제

서버 코드

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class SimpleTcpServer
{
    static void Main()
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 8080);
        listener.Start();
        Console.WriteLine("서버 시작... 연결 대기 중.");

        while (true)
        {
            using TcpClient client = listener.AcceptTcpClient();
            Console.WriteLine("클라이언트 연결됨.");

            NetworkStream stream = client.GetStream();
            byte[] buffer = new byte[256];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);

            string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"수신된 메시지: {receivedMessage}");

            string responseMessage = "서버로부터의 인사!";
            byte[] responseBuffer = Encoding.UTF8.GetBytes(responseMessage);
            stream.Write(responseBuffer, 0, responseBuffer.Length);

            Console.WriteLine("응답 전송 완료.");
        }
    }
}

클라이언트 코드

using System;
using System.Net.Sockets;
using System.Text;

class SimpleTcpClient
{
    static void Main()
    {
        try
        {
           using TcpClient client = new TcpClient("127.0.0.1", 8080);
           NetworkStream stream = client.GetStream();

           string messageToSend = "클라이언트로부터의 인사!";
           byte[] sendBuffer = Encoding.UTF8.GetBytes(messageToSend);
           stream.Write(sendBuffer, 0, sendBuffer.Length);

           Console.WriteLine($"전송된 메시지: {messageToSend}");

           byte[] receiveBuffer = new byte[256];
           int bytesRead = stream.Read(receiveBuffer, 0, receiveBuffer.Length);

           string receivedResponse = Encoding.UTF8.GetString(receiveBuffer, 0, bytesRead);
           Console.WriteLine($"수신된 응답: {receivedResponse}");
       }
       catch(Exception ex)
       {
          Console.WriteLine(ex.Message);
       }
   }
}

소켓과 관련된 주요 개념

  • 블로킹 vs 논블로킹 I/O: 애플리케이션이 블로킹 호출(작업이 완료될 때까지 실행이 대기하는 경우)을 사용할지, 논블로킹 호출(작업이 즉시 계속되는 경우)을 사용할지 이해하는 것이 중요합니다.
  • 오류 처리: 타임아웃 및 연결 끊김과 같은 잠재적 문제로 인해 소켓 작업 시 적절한 오류 처리 메커니즘을 구현해야 합니다.
  • 동시성: 서버는 종종 여러 클라이언트를 동시에 처리해야 하므로, 각 연결이 자체 스레드에서 실행될 수 있는 멀티스레딩이 필요할 수 있습니다.
  • 보안 고려사항: 네트워크를 통해 민감한 정보를 전송할 때는 항상 암호화와 같은 보안 조치를 고려해야 합니다.

결론적으로, 네트워킹 소켓을 마스터하면 개발자는 다양한 플랫폼과 장치 간에 원활한 통신이 가능한 견고한 애플리케이션을 구축할 수 있으며, C#이 제공하는 고급 기능을 활용할 수 있습니다. 이러한 개념을 이해하면 학습 여정에서 더 복잡한 네트워킹 기능을 구축할 수 있는 강력한 기초가 마련됩니다!

728x90