소켓 통신 실행 흐름


Server-Clinet 예제(1) - 기본

더보기

 

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 + "\"");

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

        // [7] 연결된 소켓을 닫는다.
        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);

        // 송수신

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

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

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

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

 

Server-Clinet 예제(2) - 통합

더보기
SocketClient01.zip
0.07MB
SocketServer01.zip
0.06MB

 

Server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

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

            // IP 및 포트 설정
            IPAddress ipaddr = IPAddress.Any;
            IPEndPoint ipep = new IPEndPoint(ipaddr, 23000);

            try
            {
                // (2) 소켓 바인딩
                listenerSocket.Bind(ipep);
                
                // (3) 연결 요청 대기 상태로 전환
                listenerSocket.Listen(5);

                Console.WriteLine("클라이언트 연결을 대기 중입니다...");

                // (4) 클라이언트 연결 수락
                Socket client = listenerSocket.Accept();
                Console.WriteLine($"클라이언트가 연결되었습니다: {client.RemoteEndPoint}");

                byte[] buff = new byte[128];
                int numberOfReceivedBytes = 0;

                while (true)
                {
                    // (5) 데이터 수신
                    numberOfReceivedBytes = client.Receive(buff);
                    Console.WriteLine($"수신한 바이트 수: {numberOfReceivedBytes}");

                    // 수신 데이터 출력
                    string receivedText = Encoding.ASCII.GetString(buff, 0, numberOfReceivedBytes);
                    Console.WriteLine($"클라이언트로부터 받은 데이터: {receivedText}");

                    // (6) 받은 데이터를 그대로 클라이언트로 전송 (에코)
                    client.Send(buff, numberOfReceivedBytes, SocketFlags.None);
                    Console.WriteLine("클라이언트에게 데이터를 다시 전송했습니다.");

                    // 'x' 입력 시 연결 종료
                    if (receivedText == "x")
                    {
                        Console.WriteLine("종료 신호(x)를 받았습니다. 서버를 종료합니다.");
                        break;
                    }

                    // 버퍼 초기화
                    Array.Clear(buff, 0, buff.Length);
                    numberOfReceivedBytes = 0;
                }
            }
            catch (Exception excp)
            {
                Console.WriteLine("예외가 발생했습니다:");
                Console.WriteLine(excp.ToString());
            }
            
            
        // (7) 연결된 소켓을 닫는다.
        client.Close();
        // 서버를 닫는다.
        listenerSocket.Close();
        }
    }
}

 

Client

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

class Client01
{
    static void Main()
    {
        //(1)
        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            //(2) + 수정 Step 2.
            IPAddress? ipaddr = null;

            Console.WriteLine("*** 소켓 클라이언트 시작 예제에 오신 것을 환영합니다. ***");
            Console.WriteLine("서버의 IP 주소를 입력하고 Enter 키를 누르세요: ");

            string? strIPAddress = Console.ReadLine();

            Console.WriteLine("유효한 포트 번호(0~65535)를 입력하고 Enter 키를 누르세요: ");
            string? strPortInput = Console.ReadLine();
            int nPortInput = 0;

            if (strIPAddress == " ") strIPAddress = "127.0.0.1";
            if (strPortInput == " ") strPortInput = "23000";

            if (!IPAddress.TryParse(strIPAddress, out ipaddr))
            {
                Console.WriteLine("잘못된 서버 IP가 입력되었습니다.");
                return;
            }
            if (!int.TryParse(strPortInput?.Trim(), out nPortInput))
            {
                Console.WriteLine("잘못된 포트 번호가 입력되었습니다. 프로그램을 종료합니다.");
                return;
            }

            if (nPortInput <= 0 || nPortInput > 65535)
            {
                Console.WriteLine("포트 번호는 0 이상 65535 이하의 값이어야 합니다.");
                return;
            }

            Console.WriteLine($"서버 정보 → IP 주소: {ipaddr} / 포트: {nPortInput}");

            clientSocket.Connect(ipaddr, nPortInput);

            Console.WriteLine("서버에 연결되었습니다!");

            //(3) + 수정 Step 2.
            Console.WriteLine("텍스트를 입력 후 Enter 키를 누르면 서버로 전송됩니다.");
            Console.WriteLine("프로그램을 종료하려면 <EXIT> 을 입력하세요.");

            string inputCommand = string.Empty;

            while (true)
            {
                inputCommand = Console.ReadLine() ?? string.Empty;

                if (inputCommand.Equals("<EXIT>"))
                {
                    break;
                }

                byte[] buffSend = Encoding.ASCII.GetBytes(inputCommand);

                //(4)
                clientSocket.Send(buffSend);

                byte[] buffReceived = new byte[128];
                int nRecv = clientSocket.Receive(buffReceived);

                Console.WriteLine("서버로부터 수신한 데이터: {0}", Encoding.ASCII.GetString(buffReceived, 0, nRecv));
            }
        }
        // + 수정 Step 1.
        catch (SocketException se) when (se.SocketErrorCode == SocketError.ConnectionRefused)
        {
            Console.WriteLine("⚠️ 연결 거절: 해당 주소/포트에서 서버가 수신 중이 아닙니다.");
            Console.WriteLine("- 서버가 실행 중인지 확인");
        }
        catch (SocketException se)
        {
            Console.WriteLine($"소켓 예외: {se.SocketErrorCode} - {se.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"예상치 못한 오류: {ex}");
        }
        finally
        {
            //(5)
            if (clientSocket != null)
            {
                if (clientSocket.Connected)
                    clientSocket.Shutdown(SocketShutdown.Both);

                clientSocket.Dispose();// Close() 생략 가능 (Dispose가 Close 포함)
            }

            //string stop = Console.ReadLine();
        }

        Console.WriteLine("아무 키나 누르면 프로그램이 종료됩니다...");
        Console.ReadKey();
    }
}