Windows 8부터 새로 생긴 WinSock의 확장 기능.

TCP, UDP, 멀티캐스트 UDP, IPv4, IPv6 모두 지원한다.

아주 높은 성능과 많은 송수신, 예측 가능성을 필요로 하는 애플리케이션에서 사용하면

네트워크 대기 시간 감소, 메시지 율 증가, 응답 시간 예측 가능성 향상을 실현할 수 있다.

 

 

현재 RIO에 대한 자료는 나온 시기에 비해서 아주 적은 편이다.

RIO에 대해서 알고 싶다면 먼저

구승모님의 'Windows Registered I/O (RIO) vs IOCP'

http://www.slideshare.net/sm9kr/windows-registered-io-rio 를 추천한다. 한글로 간단 명료하게 잘 설명 되어 있다.

 

위 자료를 이해했다면 위의 내용보다 좀 더 많은 정보를 볼 수 있는 MS Build 세미나 자료인 'New Techniques to Develop Low Latency Network Apps'를 보면 좋다.

http://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fbuild%2f2011%2fslides%2fSAC-593T_Briggs.pptx

영어이지만 구승모님 자료를 보았다면 어렵지 않게 볼 수 있다.

 

좀 더 이론 적인 부분을 보고 싶다면 아래의 자료도 좋다.

ServerFramework.com - Winsock Registered I/O Archives

http://www.serverframework.com/asynchronousevents/rio/

 

 

이제 이론을 다 보았다면 실제 코드를 보자. 역시 구승모님의 'TCP 서버 예제' https://github.com/zeliard/RIOTcpServer 가 좋다.

UDP 버전도 있다.

https://gist.github.com/ujentus/5997058/raw/48e75cf2f585ae00b19c3217a7da9e98d80f150b/RIOServer_sm9.cpp

 

Github에도 RIO 관련 라이브러리가 있으니 참고하면 좋을 듯 하다.

https://github.com/unicomp21/RIO.lib

 

자세한 API 설명은 MSDN을 참고해야 한다.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740642(v=vs.85).aspx

 

 

기존의 IOCP를 잘 이해하고 있다면 어렵지 않게 알 수 있을 것이다.

 



ps: 

1. 구글링에서 RIO는 최신 버전의 닷넷프레임워크의 네트워크 라이브러리에서 사용되고 있어서 MS에서 예제 코드나 자세한 설명이 없다는 글을 본 적이 있다.

2. RIO를 구승모님의 'Windows Registered I/O (RIO) vs IO', build 세미나 자료, 구승모님의 'TCP 서버 예제'를 보고도 이해가 안된다면 아마 IOCP 혹은 비동기 I/O에 대한 이해가 부족하다고 생각해도 될 것 같음.

저작자 표시
신고
by 흥배 2014.01.24 08:00

지금의 C++ 표준은 03 이 아닌 C++11 이다. 새로운 시대에 맞게 Asio 프로그래밍을 할 때 C++11 표준을 사용하는 것이 좋다.

 

C++03 표준을 사용하여 Asio를 사용할 때는 AsioAccept, Send, Receive 등의 비동기 함수에 완료 함수를 등록할 때 boost::bind를 사용하였지만 C++11 에서는 lambda를 사용한다.

 

Asio에서 리모트의 접속을 받아들이는 함수 async_accept C++03에서는 아래와 같은 방식으로사용했다.

 

boost::asio::ip::tcp::acceptor m_acceptor;

 

void handle_accept(Session* pSession, const boost::system::error_code& error)

{

if (!error)

{     

       std::cout << "클라이언트 접속 성공" << std::endl;

                   

       pSession->PostReceive();

}

}

 

m_acceptor.async_accept( m_pSession->Socket(),

                    boost::bind(&TCP_Server::handle_accept,

                           this,

                           m_pSession,

                           boost::asio::placeholders::error)

                    );

 

위의 코드를 C++11 방식으로 바꾸면 아래와 같다.

m_acceptor.async_accept( m_pSession->Socket(),

                     [this](boost::system::error_code error)

                    {

                       if (!error)

                       {  

                          std::cout << "클라이언트 접속 성공" << std::endl;

                          m_pSession->PostReceive();

                       }

                      

                       StartAccept();

                    }

                    );

 

 

 

저작자 표시
신고
by 흥배 2013.08.12 08:00

모바일 플랫폼으로(특히 Unity3D)로 실시간 통신 게임을 만드는 분들이 많이 사용하는 것 같다.


대충 정리 해보면 다음과 같다.

  • https://www.exitgames.com/
  • 코어 라이브러리 소스 코드는 주지 않음
  • 예제로 캐주얼 게임과 MMO 게임이 있음
  • 서버 모니터링 툴과 로그밸런스 서버 지원
  • 서버 플랫폼은 Windows만 지원
  • Reliable UDP & TCP 지원
  • 코어는 C++로 만들었고 사용은 C#로 로직 구현
  • 현재 클라이언트 라이브러리는 PC, 모바일, 웹, 콘솔 게임기 플랫폼을 지원. 프로그래밍 언어도 다양하게 지원하고 있다.
  • 클라우드 서비스도 지원(방 만들어서 하는 게임에 적합. 로직은 클라이언트로)
  • 상용 라이브러리. 동접 100명까지는 무료.
    • 현재(2013.07.19) 무제한 동접 버전이 3900 달라(1 컴퓨터 당)
    • 무제한 라이센스는 일반은 월정액으로 1500달라, 스타트업은 750 달라. 머신,게임에 상관 없음
    • 그리고 Photon으로 만든 서버가 하루에 1번 이상 ExitGames가 제공하는 라이센스 서버와 통신하지 못하면 실행 불가
      • 라이센스 서버는 구글의 AppEngine에서 서비스 되고 있다고 한다.
  • 실행
    • Photon으로 서버를 만들 때 dll 구조의 서버를 만든 후 실행은 Photon에서 제공하는 PhotonSocketServer.exe를 사용해서 실행해야 한다.
    • Lite 프로젝트를 보면 실행을 위해 설정에 이렇게 되어 있다.
시작 외부 프로그램   ..\..\deploy\bin_Win32\PhotonSocketServer.exe
명령줄 인수           /debug MyApplication /config PhotonServer.MyApp-Development.config




외국 모 게임 회사에서 근무하는 분 말로는 나름 역사도 있도 기능이나 성능 다 좋다고 한다.


개인적으로 가장 큰 문제는 라이센스 비용, 영어로 질문답, 서버는 무조건 닷넷사용 이라고 생각한다.


작은 규모의 게임에서는 사실 라이센스 비용이 싸다고 할 수 있는데 만약 규모가 커져서 서버 머신 대수가 늘어나면 그만큼 비용도 계속 늘어난다. 그리고 매일 최소 한번 이상 라이센스 서버와 통신을 해야 한다는 것도 애매한 문제.

단 인디나 작은 규모로 게임을 서비스 할 예정이라면 라이센스 비용은 크게 문제 되지 않을 듯.



Photon을 사용할 때는 라이센스 비용이 얼마큰 나갈지, 문제가 있을 때 영어로 질문답을 해야 하는데 문제 없을지 고민 해야 할 듯(이건 미들웨어를 사용할 때 고민하는 것들과 비슷한듯)


저작자 표시
신고
by 흥배 2013.08.05 08:00

Boost.Asio 활용 방법 중 괜찮을 글이 있어서 원저자의 동의를 받고 소개합니다.




boost.asio로 작성한 http client

http://devnote.tistory.com/226



WinHTTP를 쓰려다가 좌절하고… boost::asio로 작성.

#include "HttpClient.h"
void main()
{
    std::wcout.imbue( std::locale("") );
    AsioHttp::Client client;
    client.Init( "leafbird.net", CP_UTF8 );
    std::wcout << client.Request( "/index.php" ).strData << std::endl;
}

개인 프로젝트에 쓰려고 심플하게 만들었다. 이왕에 asio 사용한 김에 format같은 다른 모듈도 내부에서 사용했음. asio를 한 번도 써 본적도 없고 공부한 적도 없는데, 돌아다니다 보니 http client로 사용하는 예제 코드가 있길래 그냥 그것 기반으로 인터페이스만 정리했다.

http client를 알아볼 때 내가 단골 손님으로 들던 예제가 Naver OpenAPI인데, 이 물건으로 네이버 검색을 하려면 아래처럼 한다.

#include "HttpClient.h"
void main()
{
    std::wcout.imbue( std::locale("") );
    AsioHttp::Client client;
    // call Naver OpenAPI
    client.Init( "openapi.naver.com", CP_UTF8 );
    boost::format fmt( "/search?key=%1%&query=%2%&display..." );
    fmt % "개인 개발자 등록키 값"
        % AsioHttp::ToUrlString( "안철수" );
    std::wcout << client.Request( fmt.str().c_str() ).strData;
}

검색어로 한글을 쓰려고 보니 유의해야 할 점이 하나 있던데, UTF8 인코딩 문자만 받는다는 것. 근데 URL에서의 인코딩 문자 데이터 표기방식이 일반적으로 C++에서 쓰는 바이트 정보랑 다르다. ‘안철수’라는 문자를 UTF8로 인코딩한 후  std::string에 담은 값을 바이트 단위로 다시 ‘%’를 붙여서 문자열화 해야 됨. 바이트 데이터가 0xaa 0xbb 0xcc 0xdd 0xee 0xff라면 ‘%aa%bb%cc%dd%ff’처럼 바꿔야 한다는 말이다. 그래서 ToUrlString(...) 이라는 유틸리티 함수도 같이 만들어 두었다. 궁금한 사람은 직접 코드 열어보시오.

만약에 이 물건으로 C++ 프로젝트에서 AJAX 통신을 하겠다고 한다면, response 데이터의 처리가 문제다. 데이터 형식이 json 아니면 xml이 될 텐데.. 이전 포스팅에서도 설명했듯이 C++에서는 두 포맷 모두 심플하게 다루는 게 쉽지가 않다. 취미로 만드는 게임 엔진에 랭크 기능을 웹서버로 만들어 붙이고 통신할 목적으로 만들었는데… response를 어떻게 처리할지는 좀 더 생각해 봐야지.

저작자 표시
신고
by 흥배 2013.07.18 08:00

자기 자신(컴퓨터)의 IP 어드레스는 다음과 같은 방법으로 얻을 수 있습니다.


처음에는 IPv6 주소, 두 번째는 IPv4 주소가 나옵니다.


std::cout << "1" << std::endl; boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(), ""); boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query); boost::asio::ip::tcp::resolver::iterator end; // End marker. while (iter != end) { boost::asio::ip::tcp::endpoint ep = *iter++; std::cout << ep << std::endl; } { std::cout << "2" << std::endl; boost::asio::ip::tcp::resolver resolver(io_service);

boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(),""); boost::asio::ip::tcp::resolver::iterator it=resolver.resolve(query); while(it!=boost::asio::ip::tcp::resolver::iterator()) { boost::asio::ip::address addr=(it++)->endpoint().address(); if(addr.is_v6()) { std::cout<<"ipv6 address: "; } else std::cout<<"ipv4 address: "; std::cout<<addr.to_string()<<std::endl; } }





저작자 표시
신고
by 흥배 2013.07.04 08:00

Windows에서 TCP/IP용 서버를 만들면 최대 동접을 얼마까지 할 수 있을까?

라는 의문을 가지고 검색을 하면 적지 않게 Windows 레지스터를 바꾸어서 5000으로 늘려야 한다는 글을 볼 수 있습니다.


그런데 이 글들이 대부분이 Windows 2000 이나 2003을 기준으로 적어진 경우가 많습니다. 

그래서 지금의 최신 버전의 Windows와 틀린 부분이 많습니다.


이와 관련해서 정성태님의 블로그에 아주 좋은 글이 있어서 소개합니다.

윈도우 서버 환경에서, 최대 생성 가능한 소켓(socket) 연결 수는 얼마일까?

http://www.sysnet.pe.kr/2/0/964

위 글에서 소개된 아래 글도 보면 좋습니다. 

Configure the max limit for concurrent TCP connections 

http://smallvoid.com/article/winnt-tcpip-max-limit.html



웹에서 Windows와 관련된 글을 볼 때 한글로 된 글인 경우 Windows 2000 이나 2003 때의 이야기를 지금도 그대로 믿고 있거나 오래전에 적어진 글이 꽤 있습니다. 그래서 Windows Vista 이후와는 많이 다른 경우가 꽤 있으니 언제나 잘 확인해 보는 것이 좋습니다.


저작자 표시
신고
by 흥배 2013.06.28 08:00

Boost.Asio의 장점 중의 하나가 멀티 플랫폼을 지원하면서 각 플랫폼의 특징을 죽이지 않고 사용할 수 있도록 해주는 것이다.

 

Boost 라이브러리 1.49.0 버전에서 Windows에서 HANDLE의 비동기 조작을 할 수 있도록 해주는 windows::object_handle 클래스가 추가 되었다.

 

아래의 코드는 프로세스를 비동기로 실행 후 종료할 때까지 대기 하다가 프로세스가 종료하면 등록된 함수를 호출한다.

 

#include <iostream>

#include <string>

#include <boost/asio.hpp>

#include <boost/asio/windows/object_handle.hpp>

 

namespace asio = boost::asio;

 

void on_end_process(const boost::system::error_code& ec)

{

    if (!ec)

       {

        std::cout << "end process" << std::endl;

    }

}

 

int main()

{

    asio::io_service io_service;

 

    PROCESS_INFORMATION pi = {};

    STARTUPINFO si = {};

 

    si.cb = sizeof(si);

 

    std::string proc = "notepad";

       CreateProcessA(NULL, &proc[0], NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, (LPSTARTUPINFOA)&si, &pi);

   

    asio::windows::object_handle process(io_service, pi.hProcess);

    process.async_wait(on_end_process);

 

    io_service.run();

}

 

object_handle에는 wait/async_wait() 있으며 내부에서 WaitForSingleObjecr 호출한다. 프로세스 이외에도 CreateEvent 만든 핸들을 SetEvent 때까지 대기시킬 때도 사용할 있다.

 

 

 

 

출처: http://d.hatena.ne.jp/faith_and_brave/20120229/1330496131

 

 

저작자 표시
신고
by 흥배 2013.06.18 08:00

넷텐션의 배현직 대표님이 직접 스크린캐스트로 간단한 소셜 게임을 만드는 과정을 동영상으로 만들었더군요 

http://www.screencast.com/t/3scpMaVgb


프라우드넷 설명서와 예제 파일도 봤지만 위의 영상이 가장 쉽고 빠르게 프라우드넷을 어떻게 설명하는지 잘 보여주는 것 같습니다. 아주 강추합니다^^


이 영상을 보면 

프라우드넷을 C++을 사용하여 서버를 어떻게 만드는지, 

Unity3D에서 프라우드넷을 어떻게 사용하는지, 

프라우드넷 서버에서 DB 라이브러리를 어떻게 사용하는지 

P2P 통신을 어떻게 하는지 

등 핵심 요소를 1시간 이내의 시간으로 쉽게 알 수 있습니다.


제가 볼 때는 SDK에서 제공하는 문서나 예제 파일보다 훨쒼 좋습니다.

그리고 영상도 편집을 해서 그런지 지루한 부분 없이 스피드하게 진행되서 더 좋더군요.


참고로 영상이 여러 파일로 나누어져 있으니 각 파일을 하나씩 보면 됩니다.



저작자 표시
신고
by 흥배 2013.04.26 08:00

SCTP는 TCP/IP와 같은 프로토콜 중의 하나로 최신 기술은 아니고 2000년 10월에 RFC가 되었습니다.

현재 대부분의 리눅스 플랫폼에서는 SCTP를 OS에서 기본으로 제공하고, Windows는 OS에서 제공하지는 않고 써드파티에서 제공하고 있습니다.

 

아래의 글은 IBM의 developerworks에 있는 글을 간단하게 정리했습니다.

http://www.ibm.com/developerworks/linux/library/l-sctp/

 

 

 

SCTP에 간단한 설명

 

신뢰성 높은 범용성 있는 트랜스포트층의 프로토콜이며 IP 네트웍에서 사용할 목적으로 만듬.

 

원래는 텔레폰 시그널링을 위해서 설계된 것이지만 TCP의 제한 중 몇 개를 해결함과 동시에 UDP의 뛰어난 기능도 갖추고 있으므로 우연찮게 알게 됨.

 

SCTP의 기능은 가용과 신뢰성을 높이고, 소켓 initiation(컨넥션 확립)의 보안을 향상 시켜준다.

SCTP는 쉽게 말해서 TCP와 UDP의 장점을 가졌다고 보면 된다. TCP와 같이 신뢰성 높게 순서대로 데이터 전송을 하면서 UDP와 같이 메시지 지향으로 동작하여 메시지 경계를 유지한다. 그리고 다음과 같은 특징을 가지고 있다.

 

멀티 호밍

SCTP는 클라이언트와 서버가 두 개의 인터페이스를 통해서 접속하면 하나로 통합하여 한쪽에 문제가 발생하면 자동적으로 나머지 하나를 사용, 또는 둘 중 성능이 좋은 쪽을 자동으로 선택하여 사용한다.

 

 

멀티 스트리밍

TCP와 다르게 Association내의 복수의 스트림을 통해서 통신이 가능.

 

 

소켓 initiation 보호

TCP에서 악의적인 클라이언트가 가짜 소스 어드레스를 가진 IP 패킷을 위조하여 서버에 대량의 TCP SYN 패킷을 보내면 서버는 SYN을 수신하면 접속용 리소스를 할당하여 SYN 플랫을 다 소모하여 새로운 요구에 대응할 수 없게 된다. 이것을 Dos 공격이라고 한다.

SCTP는 4way 핸드쉐이크와 쿠키를 도입하여 이런 류의 공격에서 보호할 수 있다.

 

 

메시지 프레이밍

쉽게 말해서 이것에 의해서 패킷이 뭉쳐오지 않습니다.

현재의 TCP에서는 클라이언트에서 빠르게 두 번의 send를 하면 서버에서는 한번의 receive에 의해서 수신되어서 패킷을 나누는 로직을 구현해야 하는데 SCTP에서는 이런 것이 필요 없습니다.

 

 

구성 가능한 순서 없는 배송

TCP 처럼 순서성 있는 전달을 할 수 있지만 필요에 따라서 UDP처럼 비순서 전달을 할 수도 있다.

 

 

그레이스풀 셧 다운

 

 

 

신고
by 흥배 2012.10.22 09:00

IPv4에서만 사용


IP 문자열 -> 정수


inline UINT32 ConvertIP(const char* szIP)
{
    SOCKADDR_IN Addr;
    memset(&Addr, 0, sizeof(SOCKADDR_IN));

    unsigned int nIP = inet_addr(szIP);
    if (nIP != INADDR_NONE)
    {
        memcpy(&(Addr.sin_addr), &nIP, sizeof(UINT32));
    }
    else
    {
        HOSTENT* pHostInfo = gethostbyname(szIP);
        if (pHostInfo == NULL) return INADDR_NONE;

        memcpy((char FAR *)&(Addr.sin_addr), pHostInfo->h_addr, pHostInfo->h_length);
    }

    return static_cast<UINT32>(Addr.sin_addr.S_un.S_addr);
}




IP 정수 -> IP 문자열


void NumberToIPString( const UINT32 nIP, const INT32 nMaxIPStrLen, char* szIP )
{
    SOCKADDR_IN Addr;
    memset(&Addr, 0, sizeof(sockaddr_in));

    Addr.sin_addr.S_un.S_addr = nIP;
    strcpy_s( szIP, nMaxIPStrLen, inet_ntoa(Addr.sin_addr) );
}



저작자 표시
신고
by 흥배 2012.09.19 09:00
| 1 2 |

티스토리 툴바