새소식

C#/Network

2. .Net Socket 예제

  • -

 

 

프로그래밍 기술을 바라보는 개발자의 관점

모든 프로그래밍 기술은, 현실의 문제를 컴퓨터를 사용해 해결하는 하나의  방법일 뿐이다.

모든 프로그래밍 기술은, 인간이 사용해왔고, 현실에 존해하는 방법과 동일하다.

대표적으로 데이터베이스와 네트워크가 현실의 도서관과 물류 운송과 개념이 같다.

 

 

네트워크 개념


네트워크 동작은 물류  시스템과 비슷하다.

운송하는 대상이 상품에서 데이터로 변경되었을 뿐이다.

물류 운송처럼 네트워크 통신은 어떤 기기의 저장장치에 있는 데이터를 다른 기기에 저장장치로 옮기는 것이다.

 

문제가 있다면, 물류 센터의 시스템이 복잡하듯, 네트워크 통신은 서버의 데이터를 관리하는 방법이 어렵다.  

 

우체국 택배를 보내는 절차와 통신 절차를 비교해보자.

  물류 통신
대상 물건 데이터
1 상품의 크기에 맞춰 규격이 정해진 박스를 준비한다. 데이터 크기에 맞는 버퍼와 자료형을 선택한다.
2 송장에 보내는 곳, 받는 곳의 주소를 적는다. 보내는 기기의 IP 주소 와 포트 정보
받는 기기의 IP 주소 와 포트 정보를 사용한다.
3 운송 회사가 정해놓은 규칙에 맞춰 가격 및 영수증, 운송 정보를 확인할 수있다. 데이터의 특성에 맞는 전송 규칙인 프로토콜을 선택한다.
4 목적지에 잘 도착했다는 연락을 받는다. 통신 과정에서 프로토콜이 데이터의 송수신 성공과 실패에 대한 처리를 담당한다.

 

IP & Port


IP : 주소

Port : 받는사람

 

 

IP 주소

Internet Protocol

네트워크 통신과 택배가 다른점은, 네트워크 통신은 데이터 주고 받는 과정이 발생한다.

이 때, 출발지와 목적지를 특정하기 위해 네트워크는 IP 라는 고유 식별 정보를 사용한다.

현실의 주소가 중복되지 않듯이,네트워크 IP는 중복되지 않는다.

 

 

Port 번호

택배를 받을 때, 목적지까지 도착하는것은 주소만으로 가능하다.

하지만 목적지에 여러 사람이 있다면, 수신자가 누군지 명확하게 식별할 사람의 이름이 필요하다.

네트워크도 마찬가지다. 목적지에 해당하는 장치까지는 IP 주소로 찾아 갈 수 있지만, 기기의 어떤 프로램이 이 데이터를 필요로 하는지 알기 위해서 Port 번호라는 것을 사용한다.

Port 번호는 네트워크 목적지(장치)의 실행중인 프로그램을 식별하는데 사용한다. 

 

 

EndPoint


 

닷넷(.NET) IP 설정

System.Net의 IPAddress 클래스를 사용한다.

일반적으로 IPv4 주소체계 기반으로 IPAddress 객체를 생성하여 IP 주소를 변수 형태로 사용

문자열 파싱, 바이트 배열, 정수 입력할 수 있다.

using System;
using System.Net;

namespace NetworkTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // 문자열 파싱
            IPAddress ip1 = IPAddress.Parse("192.168.1.13");

            // 바이트 배열
            IPAddress ip2 = new IPAddress(new byte[] { 192, 168, 1, 13 });

            // 정수 사용, 218212544를 변환하면 13.1.168.192 된다.(빅엔디안)
            IPAddress ip3 = new IPAddress(218212544);
            Console.WriteLine(ip3.ToString());  // "192.168.1.13" 출력     

            // 4
            IPAddress ip4 = IPAddress.Parse("216.58.216.174");
            byte[] ipbytes = ip4.GetAddressBytes(); // IP를 바이트배열로 변환
            IPAddress ipv6 = ip4.MapToIPv6();  // IPv4를 IPv6로 매핑
            Console.WriteLine(ipv6.ToString());
        }
    }
}

 

EndPoint

IPEndPoint 클래스

EndPoint(종단점)

TCP나 UDP는 IP 주소와 함께 Port번호를 사용한다.

IPEndPoint는 IP주소와 포트를 받아들인 것으로 ToString() 메서드를 호출하면 "IP주소:포트" 형식으로 문자열을 리턴하거나 IP 주소 변환 등 편의 기능을 사용 할 수 있다.

 

 

Socket 통신 흐름 예제


Socket_Client.zip
0.17MB
Socket_Server.zip
0.17MB

Server

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

class Program
{
    static void Main(string[] args)
    {
        // [1] 서버 소켓 생성
        Socket Server_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // [2] IP, Port 를 "서버 소켓"에 등록
        //Server_Socket.Bind(new IPEndPoint(IPAddress.Any, 7000));
        IPEndPoint ipt = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7000);
        Server_Socket.Bind(ipt);

        // [3] 준비된 "서버 소켓"이 클라이언트의 접속 요청을 대기하도록 명령
        // 일반적으로 listen은 접속요청이 올 때까지, 블록되어 대기 상태
        Server_Socket.Listen(100);

        // 클라이언트로부터 대기준인 서버 소켓으로 접속 요청이 들어오면 Listen()이 다음 로직을 진행한다.
        // [4] 대기중인 서버 소켓이 Aceept( )를 실행하고, 서버는 클라이언트와 연결이 성공된 소켓을 하나 더 만든다.  
        Socket Connected_Socket = Server_Socket.Accept(); // 블로킹 함수

        // 데이터를 주고 받는 규격 상자 (택배 상자)
        // 정해진 버퍼 크기만큼 주고 받기로 약속되어야 한다.
        byte[] receiverBuff = new byte[2048];

        // [5] 서버 로직은, 연결된 소켓으로 데이터를 주고 받는다.
        int len = Connected_Socket.Receive(receiverBuff);
        string data = Encoding.UTF8.GetString(receiverBuff, 0, len);
        Console.WriteLine("전달받은 데이터 문장 >> \"" + data + "\"");

        // 받은것을 다시 보낸다.(Echo)
        Connected_Socket.Send(receiverBuff);

        // [6] 연결된 소켓을 닫는다.
        Connected_Socket.Close();

        // 서버를 닫는다.
        Server_Socket.Close();

    }
}

Clinet

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

class Program
{
    static void Main(string[] args)
    {
        // [1] 클라이언트 소켓 생성
        Socket Client_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // IP, Port를 IPEndPoint 객체로 만들고, 접속 할 서버의 IP, PORT 정보를 준비한다.
        IPEndPoint ipt = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7000);

        // [2] 클라이언트 소켓은 Connect 함수를 사용하여 서버로 접속 요청한다.
        Client_Socket.Connect(ipt);

        // [3] 송수신

        // 데이터를 주고 받는 규격 상자 (택배 상자)
        // 정해진 버퍼 크기만큼 주고 받기로 약속되어야 한다.
        byte[] sendBuff = new byte[2048];

        // 보낸다.
        string msg = "안녕하세요";
        byte[] buffer = Encoding.UTF8.GetBytes(msg);
        Client_Socket.Send(buffer);

        // 받는다.
        byte[] receiverBuff = new byte[2048];
        int len = Client_Socket.Receive(receiverBuff);
        string data = Encoding.UTF8.GetString(receiverBuff, 0, len);
        Console.WriteLine(data);

        // [4] 닫는다.
        Client_Socket.Close();
    }
}

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.