유용한 소켓 강좌

** 원본 소켓 강좌 보기 **


----  이하 퍼온 강좌  ---------

Network의 기본


소켓 API


I/O 모델


POSIX Thread


함수 포인터 관련..

http://www.newty.de/fpt/index.html

windows 기반의 c++에서는

[CODE type=c++]
int (CFunc::*func)( int, int );
func = CFunc::GetArea;
CFunc A;
(A.*func)( x, y );
[/CODE]

[출처]
http://izeph.com/tt/blog/155


위 코드 처럼 Class의 맴버 메소드를 함수포인터로 사용할 수 있지만,
unix 기반에서는 사용 할 수가 없다.

unix 기반에서 사용하려면,

[CODE type=c++]
class TClassA
{
public:
  void Display(const char* text) { cout << text << endl; };
  static void Wrapper_To_Call_Display(void* pt2Object, char* text);
};
void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string)
{
  TClassA* mySelf = (TClassA*) pt2Object;
  mySelf->Display(string);
};
void DoItA(void* pt2Object, void (*pt2Function)(void* pt2Object, char* text))
{
  pt2Function(pt2Object, "hi, i'm calling back using a argument ;-)");  // make callback
};
void Callback_Using_Argument()
{
  TClassA objA;
  DoItA((void*) &objA, TClassA::Wrapper_To_Call_Display);
}
[/CODE]

[출처]
http://www.newty.de/fpt/callback.html#member

이렇게 래퍼를 한번 거쳐 사용해야 한다.

UTF-8 을 EUC-KR 로 변환

libxml2를 사용하여 파싱을 하게되면 한글이 무조건 utf-8로 변환되어 버리더군요.
문제 해결을 위해 iconv라이브러리를 사용했습니다.

[CODE type=c++]
#ifndef _UTF8TOEUCKR
#define _UTF8TOEUCKR

#include
static int UTF8toEUCKR( char *outBuf, int outLength, char *inBuf, int inLength )
{
iconv_t cd = iconv_open( "EUC-KR", "UTF-8" );

int ires = (int)iconv( cd, &inBuf, (size_t*)&inLength, &outBuf, (size_t*)&outLength );

iconv_close(cd);

return ires;
}

#endif
[/HTML][/CODE]
[참고]
http://www.redwiki.net/wiki/wiki.php/iconv#s-3.1.1
http://www.pie.pe.kr/cgi-bin/moin.cgi/LibIconv
http://www.gnu.org/software/libiconv/

MFC용 ADO클래스 (버전업)

미루고 미루던 작업을 디드어 했습니다. ㅎㅎ
하나의 커넥션을 끊지 않고, 계속 활용하도록 수정했습니다.

원본보기

[CAdoDB.h] =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

[CODE type=c++]
#ifndef __ADODB_HEADER_B694B3CA_2D77_4AC8_95E3_DBA44C3DB329__

#define __ADODB_HEADER_B694B3CA_2D77_4AC8_95E3_DBA44C3DB329__
/*******************************************************************
*
* MDB를 OLE로 연결한다.
* 하나의 connection로 모든 처리를 한다.
*
* ** 반드시 클래스 사용전 CoInitialize()함수를 호출해
* COM Object사용을 초기화 해야 한다.
*
*
* Usage:
* CAdoDB db;
* db.Init( "test.mdb" );
* db.Open( sql );
* while( db.IsEOF() == FALSE )
* {
* value = db.GetValueString( "field" );
* db.MoveNext();
* }
* db.Close();
*
* db.Excute( sql );
*
*
*
* 2006-07-21
*
* By newtype / newtype@newtype.pe.kr / http://newtype.pe.kr/
*
/****************************************************************/

#pragma once

#import "msado26.tlb" rename ("EOF","adoEOF") no_namespace
/*
#import "C:\program files\common files\system\ado\msado15.dll" \
no_namespace \
rename("EOF", "adoEOF")
*/


class CAdoDB
{
public:
CAdoDB(void);
~CAdoDB(void);
BOOL Init(CString Filename);
BOOL Connection(CString Filename = _T(""));
BOOL CloseConneciton();
BOOL Open(CString sql, CString Filename = _T(""));
BOOL Close();
BOOL IsEOF();
CString GetValueString(CString Field);
int GetValueInt(CString Field);
BOOL MoveNext();
BOOL Excute(CString sql, CString Filename = _T(""));

_ConnectionPtr GetConnection();
void AttachConnection( _ConnectionPtr conn );
void DetachConnection();


private:
_ConnectionPtr m_pConn;
_RecordsetPtr m_pRs;
CString m_strConnection;
BOOL m_IsOpen;
BOOL m_IsConn;

BOOL FileCmp( CString Filename );
};


#endif // __ADODB_HEADER_B694B3CA_2D77_4AC8_95E3_DBA44C3DB329__

[/HTML][/CODE]
[CAdoDB.cpp] =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
[CODE type=c++]
/* AdoDB.cpp */
#include "adodb.h"

/*******************************************************************
* OLE DB connection string
*******************************************************************/
const TCHAR *oleString = _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=");


/********************************************************************
* 기본 생성자
*
* connection객체와 recordset객체를 생성한다.
********************************************************************/
CAdoDB::CAdoDB(void)
{
if ( FAILED(m_pConn.CreateInstance(__uuidof(::Connection))) )
AfxMessageBox(_T("Connection COM 객체 생성에 실패 하였습니다."), MB_OK, NULL);

if ( FAILED(m_pRs.CreateInstance(__uuidof(Recordset))) )
AfxMessageBox(_T("Recordset COM 객체 생성에 실패 하였습니다."), MB_OK, NULL);

m_strConnection = _T("");
m_IsOpen = FALSE;
}



/********************************************************************
* 기본 소멸자
*
* connection객체와 recordset객체를 close하고 반환 한다.
********************************************************************/
CAdoDB::~CAdoDB(void)
{
Close();
CloseConneciton();

m_pRs.Release();
m_pConn.Release();
}



/********************************************************************
* 연결 문자열을 만든다.
* 기존 파일명과 틀릴때에만 connection을 닫고, 연결문자열을 만든다.
*
* return : BOOL : TRUE | FALSE
*
* parameter :
* [in] CString Filename : MDB 파일명
********************************************************************/
BOOL CAdoDB::Init(CString Filename)
{
if ( m_pRs==NULL || m_pConn==NULL )
return FALSE;

if ( Filename.IsEmpty() )
return FALSE;

if ( FileCmp( Filename ) == TRUE )
return TRUE;

Close();

m_strConnection = oleString + Filename;

return FALSE;
}



/********************************************************************
* DB에 연결한다.
* 기존 connection이 있으면 유지 한다.
*
* return : BOOL : TRUE | FALSE
*
* parameter :
* [in] CString Filename : MDB 파일명
********************************************************************/
BOOL CAdoDB::Connection(CString Filename)
{
if ( Filename.IsEmpty() && m_strConnection.IsEmpty() )
return FALSE;

if ( Filename.IsEmpty() == FALSE )
{
Init( Filename );
}

if ( m_pConn == NULL )
return FALSE;

if ( m_IsConn == TRUE )
return TRUE;

try
{
m_pConn->Open( (_bstr_t)m_strConnection, "","" ,adConnectUnspecified );

m_IsConn = TRUE;
}
catch(_com_error &err)
{

m_IsConn = FALSE;

TRACE("Error : %s : DB CONNECTION FAIL\n", err.Description() );
}

return m_IsConn;
}



/********************************************************************
* 레코드 셋을 오픈 한다.
* 기존 recordset이 있으면 close 한다.
*
* return : BOOL : TRUE | FALSE
*
* parameter :
* [in] CString sql : SQL Query SELECT 구문
* [in] CString Filename : MDB 파일명
********************************************************************/
BOOL CAdoDB::Open(CString sql, CString Filename)
{
HRESULT hr;
VARIANT conn;

if ( m_pConn == NULL || m_pRs == NULL )
return FALSE;

if ( Filename.IsEmpty() == FALSE )
{
Connection(Filename);
}
else
{
Connection();
}

if ( m_IsConn == FALSE )
return FALSE;

if ( m_IsOpen == TRUE )
Close();

try
{
//TRACE( sql );
TRACE( "\n" );

VariantInit(&conn);
conn.pdispVal=m_pConn;
conn.vt=VT_DISPATCH;

hr = m_pRs->Open( (LPTSTR)(LPCTSTR)sql, conn,
adOpenForwardOnly, adLockOptimistic, adCmdUnknown);
}
catch(_com_error &e)
{
TRACE("\tDescription: %s\n", (LPCTSTR) e.Description());
}
catch(...)
{
TRACE("*** Unhandled Exception ***\n");
}

if ( SUCCEEDED( hr ) )
m_IsOpen = TRUE;

if ( sql.TrimLeft().Left(7).CollateNoCase( "SELECT " ) )
{
m_IsOpen = FALSE;
}

return SUCCEEDED( hr );
}



/********************************************************************
* 더 이상 튜플이 없으면 TRUE를 반환 한다.
*
* return : BOOL : TRUE | FALSE
*
* parameter : None
********************************************************************/
BOOL CAdoDB::IsEOF()
{
if ( !m_IsOpen )
return TRUE;

return (BOOL)m_pRs->GetadoEOF();
}



/********************************************************************
* 현재 튜플의 Field에 해당하는 Instance를 문자열 형태로 얻는다.
*
* return : CString : Value
*
* parameter :
* [in] CString Field : 값을 가져올 Attribute Name
********************************************************************/
CString CAdoDB::GetValueString(CString Field)
{
if ( !m_IsOpen || IsEOF() )
return "";

_variant_t vt = m_pRs->GetCollect( (LPTSTR)(LPCTSTR)Field );

return ( (vt.vt == VT_NULL)? ("") : vt );
}


/********************************************************************
* 현재 튜플의 Field에 해당하는 Instance를 정수 형태로 얻는다.
*
* return : int : Value
*
* parameter :
* [in] CString Field : 값을 가져올 Attribute Name
********************************************************************/
int CAdoDB::GetValueInt(CString Field)
{
return atoi( GetValueString(Field) );
}


/********************************************************************
* 다음 튜플로 이동한다.
*
* return : BOOL : TRUE | FALSE
*
* parameter : None
********************************************************************/
BOOL CAdoDB::MoveNext()
{
if ( !m_IsOpen )
return FALSE;

return SUCCEEDED( m_pRs->MoveNext() );
}


/********************************************************************
* recordset을 닫는다.
*
* return : BOOL : TRUE | FALSE
*
* parameter : None
********************************************************************/
BOOL CAdoDB::Close()
{
if ( m_IsOpen == FALSE )
return TRUE;

m_IsOpen = FALSE;

return SUCCEEDED( m_pRs->Close() );
}


/********************************************************************
* connection을 끊는다.
*
* return : BOOL : TRUE | FALSE
*
* parameter : None
********************************************************************/
BOOL CAdoDB::CloseConneciton()
{
if ( m_IsConn == FALSE )
return TRUE;

m_IsConn = FALSE;

return SUCCEEDED( m_pConn->Close() );
}


/********************************************************************
* DML 쿼리를 실행한다.
* connection이 없으면 연결한다.
*
* return : BOOL : TRUE | FALSE
*
* parameter :
* [in] CString sql : SQL Query DML 구문
* [in] CString Filename : MDB 파일명
********************************************************************/
BOOL CAdoDB::Excute(CString sql, CString Filename /*= _T("")*/)
{
if ( m_pConn == NULL )
return FALSE;

if ( Filename.IsEmpty() == FALSE )
{
Connection(Filename);
}
else
{
Connection();
}

if ( m_IsConn == FALSE )
return FALSE;

try
{
TRACE( sql );
TRACE( "\n" );

m_pConn->Execute( (_bstr_t)sql, NULL, adCmdText );
}
catch(_com_error &err)
{
TRACE("Error : %s : DB Execute FAIL\n", err.Description() );
return FALSE;

}

return TRUE;
}



/********************************************************************
* 기존에 연결 파일명과 비교해 틀리면 FALSE를 반환한다.
* (개선의 여지가 있음.
* 파일명에 경로가 포함될 경우 정확한 비교가 되지 않음 )
*
* return : BOOL : TRUE | FALSE
*
* parameter :
* [in] CString Filename : MDB 파일명
********************************************************************/
BOOL CAdoDB::FileCmp( CString Filename )
{
if ( m_IsConn == FALSE )
return FALSE;

return m_strConnection.CompareNoCase( oleString + Filename ) == 0;
}


/********************************************************************
* 현재 connection을 얻는다.
*
* return : _ConnectionPtr
*
* parameter : None
* [in] CString Filename : MDB 파일명
********************************************************************/
_ConnectionPtr CAdoDB::GetConnection()
{
return m_pConn;
}



/********************************************************************
* connection을 새로 Attach한다.
* 이미 사용중인 connection 및 Recordset는 닫는다.
*
* return : None
*
* parameter :
* [in] _ConnectionPtr conn : 사용할 Connection Object
********************************************************************/
void CAdoDB::AttachConnection( _ConnectionPtr conn )
{
if ( m_IsOpen == TRUE )
Close();

if ( m_IsConn == TRUE )
{
CloseConneciton();
m_pConn.Release();
}

m_pConn = conn;
m_IsConn = TRUE;
}

/********************************************************************
* connection을 새로 Attach한다.
* 이미 사용중인 connection 및 Recordset는 닫는다.
*
* return : None
*
* parameter :
* [in] _ConnectionPtr conn : 사용할 Connection Object
********************************************************************/
void CAdoDB::DetachConnection()
{
if ( m_IsConn == FALSE )
return;

m_pConn = NULL;
m_IsConn = FALSE;
}
[/HTML][/CODE]

소스상에서 lib링크 하기

아래의 프리컴파일러 헤더를 사용 합니다. [CODE type=c++] #pragma comment(lib, "library.lib") [/HTML][/CODE]

socket 타임아웃처리

Unix socket 에서 타임아웃 처리를 하는 방법중에 select를 이용한 방법입니다.

[CODE type=c++]
/********************************************************************
* 데이타를 보낸다.
*
* return : int Error Code
* parameter :
* [in] int sock : 연결할 소켓 핸들
* [in] void *data : 전송할 데이타
* [in] unsigned int size : 데이타의 크기
* [in] int timeout : 타임아웃 처리를 할 시간
********************************************************************/
int gaSend(int sock, void *data, unsigned int size, int timeout)
{
    int sockNum = sock +1;
    fd_set sockSet;
    struct timeval selTimeout = { timeout, 0 }; /* 초, 마이크로초 */
    int result;

    if ( sock == 0 )
        return CONNECTION_REFUSED;

    FD_ZERO(&sockSet);
    FD_SET(sock, &sockSet);

    result = select( sockNum, NULL, &sockSet, NULL, &selTimeout );
    if ( result == 0 )
    {
        return CONNECTION_TIMEOUT;
    }
    else if ( result ==-1 )
    {
        return CONNECTION_REFUSED;
    }

    result = socketSend( sock, (char*)data, size) ;
    if ( result < 0 )
    {
        return CONNECTION_REFUSED;
    }

    return SUCCESS;
}

/********************************************************************
* 데이타를 받는다.
*
* return : int Error Code
* parameter :
* [in] int sock : 연결할 소켓 핸들
* [in] void *data : 전송받을 데이타
* [in] unsigned int size : 데이타의 크기
********************************************************************/
int gaRecive(int sock, void *data, unsigned int size, int timeout)
{
    int sockNum = sock +1;
    fd_set sockSet;
    struct timeval selTimeout = { timeout, 0 };
    int result;

    if ( sock == 0 )
        return CONNECTION_REFUSED;

    FD_ZERO(&sockSet);
    FD_SET(sock, &sockSet);

    result = select( sockNum, &sockSet, NULL, NULL, &selTimeout );
    if ( result == 0 )
    {
        return CONNECTION_TIMEOUT;
    }
        else if ( result ==-1 )
    {
        return CONNECTION_REFUSED;
    }


    result = socketRecv(sock, (char*)data, size, timeout);
    if( result < 0 )
    {
        return CONNECTION_REFUSED;
    }

    return SUCCESS;
}
[/HTML][/CODE]

LPTSTR 자료형의 문자열 치환

UINT Replace( LPTSTR target, LPCTSTR source, LPCTSTR find, LPCTSTR replace )
{
       UINT i, nCount=0;
       BOOL bFind;
       LPCTSTR ps, pf;
       LPTSTR buf=NULL, pt = target;

       size_t nLenSrc = _tcslen( source );

       buf = new TCHAR[nLenSrc+1];
       if ( buf == NULL )
               return NULL;

       _tcsncpy( buf, source, nLenSrc );
       buf[nLenSrc] = 0;


       for(ps=buf; *ps; ps++)
       {
               if ( find[0] == *ps )
               {
                       bFind = TRUE;
                       for(pf=find+1, i=1; *pf; pf++, i++)
                       {
                               if ( *pf != ps[i] )
                               {
                                       bFind = FALSE;
                                       break;
                               }
                       }

                       // 찾았다!
                       if ( bFind )
                       {
                               for(pf=replace; *pf; pf++)
                                       *(pt++) = *pf;
                               ps += (--i);

                               nCount++;

                               continue;
                       }
               }

               *(pt++) = *ps;
       }

       *pt = 0;

       delete[] buf;

       return nCount;
}

UTF8, 유니코드, 아스키 파일의 구별

* ANSI 텍스트 파일
- 특별한 표식이 없습니다.

* 유니코드 (little endian)
파일 처음에 0xFF 0xFE 의 두바이트로 시작합니다.

* 유니코드 (big endian)
파일 처음에 0xFE 0xFF 의 두바이트로 시작합니다.

* UTF-8
파일을 덤프 해본 결과 파일 처음에 0xEF 0xBB 0xBF 의 세바이트로 시작합니다.



한번 파일을 만든후 덤프 해보시기 바랍니다
그럼 즐삽

항상 위 효과 내기

[CODE type=c++]
// CDialog를 상속받아
// OnCancel()과 DoModal()을 오버라이딩 한다.



// 닫아도 닫히지 않는다 숨길뿐...
void CMyDlg::OnCancel()
{
       ShowWindow( SW_HIDE );
       SetWindowPos( &wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
       AfxGetMainWnd()->SetFocus();
}

// Dlg를 모달로 연다
INT_PTR CMyDlg::DoModal()
{
       ShowWindow( SW_SHOW );
       SetWindowPos( &wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

       return 0;
}



// 생성한 후
CMyDlg *pMyDlg = new CMyDlg();
pMyDlg->Create( IDD_DIALOG_MY, CWnd::FromHandle(::GetDesktopWindow()) );
pMyDlg->DoModal();



// 숨겨져 있으면 보여준다.

if ( m_pMyDlg->ShowWindow( SW_SHOWNA ) == SW_HIDE )
        pMyDlg->DoModal();

[/CODE]

문자열 분할시, 특정 번째 문자열 얻기

제목이 어렵네요.. ㅡㅡ;
소스 보시면 어려운것 없으니 금방 이해 하실겁니다.
좋은 시간 되세요..^^


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//--------------------------------------------------------------------------//
//Fuction        : Splite
//Parameter : LPTSTR lpszDest, LPCTSTR lpcszSorc, TCHAR cSep, int nIndex
//Return        : LPCTSTR
//Note                : lpcszSorc를 cSep로 나누어서 nIndex번째 문자열을 lpszDest에 넣는다.
//--------------------------------------------------------------------------//
LPCTSTR Splite( LPTSTR lpszDest, LPCTSTR lpcszSorc, TCHAR cSep, int nIndex)
{
       int i, j, k, l;
       int count;

       count = (int)strlen(lpcszSorc);
       for (i=j=k=l=0; i<count && l<=nIndex; i++)
       {
               if ( *(lpcszSorc+i) == cSep )
               {
                       k=i;
                       strncpy( lpszDest, lpcszSorc+j, k-j );
                       lpszDest[k-j] = 0;
                       j=k+1;
                       l++;
               }
       }

       return lpszDest;
}