ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [boost asio] 동기식 echo 채팅 서버
    C_C++ 프로그래밍/boost 2019. 7. 31. 20:38

     

         로재의 개발 일기      

    boost asio

    전에 boost에 대해서 설명한 바가 있고, 설치하여 사용하는 법까지 알아보았다.

    이번에는 네트워크 통신에 자주 사용이 되고 있는 boost asio의

    동기식 채팅 예제를 들면서 Winsock와 비교하면서 알아보겠다.



      synchronous_server.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #include <boost/asio.hpp>
    #include <iostream>
     
    #pragma warning (disable : 4996);
     
    constexpr char SERVER_IP[] = "127.0.0.1";
    constexpr unsigned short PORT_NUMBER = 1234;
     
    int main() {
        boost::asio::io_service io_service;
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), PORT_NUMBER);
        boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
     
        boost::asio::ip::tcp::socket socket(io_service);
        acceptor.accept(socket);
     
        std::cout << "Client Enter" << std::endl;
     
        while(1
        {
            std::array<char128> buf;
            buf.assign(0);
            boost::system::error_code error;
            size_t len = socket.read_some(boost::asio::buffer(buf), error);
     
            if (error) {
                if (error == boost::asio::error::eof) {
                    std::cout << "Connect lost client" << std::endl;
                }
                else {
                    std::cout << "error No: " << error.value() << "error Message: "
                        << error.message() << std::endl;
                }
                break;
            }
     
            std::cout << "Client's message: " << &buf[0<< std::endl;
            char echoMessage[128= { 0, };
            sprintf_s(echoMessage, 128 - 1"%s"&buf[0]);
            int nMsgLen = strnlen_s(echoMessage, 128 - 1);
     
            boost::system::error_code ignored_error;
            socket.write_some(boost::asio::buffer(echoMessage, nMsgLen), ignored_error);
            std::cout << "Client's Message: " << echoMessage << std::endl;
        }
        getchar();
        return 0;
    }
    cs




    1
     boost::asio::io_service io_service;
    cs

    boost::asio::io_service는 Boost.asio의 핵심 중의 핵심으로.

    io_service는 커널에서 발생한 io 이벤트는 디스패치( 다중 작업 중 높은 작업 수행을 위한 자원 할당)

    을 해주는 클래스이며, io_service를 통해서 접속 받기, 접속하기, 데이터 받기, 데이터 보내기가 가능해진다.


    즉, boost에서 socket을 생성하여 접속 및 데이터 송수신 처리를 위해서는 io_service가 필수인 셈이다.




    1
    2
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), PORT_NUMBER);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
    cs

    endpoint는 네트워크 주소를 설정한다.

    acceptor 클래스는 클라이언트의 접속을 받아들이는 역할을 한다.


    즉 위의 코드의 경우에는 endpoint로 네트워크 주소를 설정해준 이후에

    endpoint와 io_service를 연결시켜 클라이언트의 접속을 받는다.



    1
    2
    boost::asio::ip::tcp::socket socket(io_service);
    acceptor.accept(socket);
    cs

    위의 소스코드는 tcp를 사용하도록 명시하였기 때문에.

    클라이언트에 할당될 socket을 만들어야 한다.

    그리고 그 소켓을 통해서 클라이언트가 보낸 메시지를 주고 받아야 하기 때문에

    io_service에 할당을 해줘야 한다.



    1
    size_t len = socket.read_some(boost::asio::buffer(buf), error);
    cs

    socket의 멤버함수인 read_some을 사용하여 클라이언트가 보낸 데이터를 받는다.

    인자로 데이터를 받을 버퍼와 에러 코드를 받을 error_code를 사용하며 데이터를 받으면

    받은 데이터 크기를 반환하게 된다.



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if (error) {
        if (error == boost::asio::error::eof) {
            std::cout << "Connect lost client" << std::endl;
        }
        else {
            std::cout << "error No: " << error.value() << "error Message: "
                << error.message() << std::endl;
        }
        break;
    }
    cs

    error_code를 조사해서 클라이언트가 받은 데이터의 에러 유무를 조사한다.

    클라이언트의 접속이 끊어지는 경우에는 read_some을 통해서 알 수 있다.

    이때는 eof 값이 들어가기 때문에, 적절하게 출력 및 종료를 시켜주면 된다.




    1
    socket.write_some(boost::asio::buffer(echoMessage, nMsgLen), ignored_error);
    cs

    이제 write_some을 통해서 write 작업을 해준다.

    이 부분도 read_some처럼 error_code를 함께 인자를 주어 보내지만, 보낼 데이터의 크기를 미리 

    지정하여 지정한 데이터 크기만큼 보낸다.


    ※ 본 글은 개인 포트폴리오 혹은 공부용으로 사용하기 때문에, 무단 복사 유포는 금지하지만, 개인 공부 용도로는 얼마든지 사용하셔도 좋습니다



    반응형
Designed by Tistory.