이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4FE7CE007255739A07C68401
원문 작성일 : 2012.06.25

 

------------------------------------------------------------------------------------------

 

첨부파일 : getChar.zip

 

 

getchar() 함수를 클래스화 시켜서 좀 편하게 써보자 생각함.
getChar.h 랑 getChar.cpp 두개의 파일을 둠.
쉽게 생각했다가 프로그램 종료 시, getchar() 에서 블럭걸리는 증상 발견됨.
하루종일 방법을 고민하다 못찾고 kldp 에 물어 봄.
http://kldp.org/node/133482
pipe(), select() 함수를 사용하여 어케어케 함. 공부할게 생겼다.
위 답변을 가지고 아래처럼 정리하여 동작함을 확인하였다.
제일 아래 main.cpp 에 클래스 사용 예제가 있다.

 


############ getChar.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _GETCHAR_H_
#define _GETCHAR_H_
#include "pthread.h"
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
 
class CGetChar
{
public :
        CGetChar() ;
        ~CGetChar() ;
        int init(CALLBACK_GETCHAR callback) ;
        int stop() ;
        int destroy(void) ;
 
        // This only use in callback function.
        CALLBACK_GETCHAR m_callbackGetChar ;
        int m_flagStop ;
private :
        pthread_t m_thGetChar ;
};
#endif
 

 

 

 

############ getChar.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "getChar.h"
#include<stdio.h>
#include<termio.h>
#include<unistd.h>
#include<fcntl.h>
 
static int poll_getch[2] = {-1, -1} ;
 
void* threadGetChar(void* pData)
{
        int fd_cancel, fd_stdin, ch ;
        struct termios org_term, new_term ;
        fd_set rdfds ;
        int max_fd ;
        int r ;
        CGetChar* pGetChar = (CGetChar*)pData ;
 
        while(1)
        {
                fd_cancel = poll_getch[0] ;
                fd_stdin = fileno(stdin) ;
 
                ch = -1 ;
                tcgetattr(fd_stdin,&org_term) ;
                new_term = org_term ;
                new_term.c_lflag&= ~(ICANON | ECHO) ;
                new_term.c_cc[VTIME] = 0 ;
                new_term.c_cc[VMIN] = 1 ;
                tcsetattr(fd_stdin, TCSANOW,&new_term) ;
 
                FD_ZERO(&rdfds) ;
                FD_SET(fd_stdin,&rdfds) ;
                FD_SET(fd_cancel,&rdfds) ;
 
                max_fd = fd_stdin>fd_cancel ? fd_stdin : fd_cancel ;
 
                r = select(max_fd + 1,&rdfds, NULL, NULL, NULL) ;
 
                if( r>0&&FD_ISSET(fd_stdin,&rdfds))
                        ch = getchar() ;
 
                tcsetattr(fd_stdin, TCSANOW,&org_term) ;
                pGetChar->m_callbackGetChar(ch) ;
 
                if(pGetChar->m_flagStop)
                        break ;
 
                usleep(1000) ;
        }
        return 0 ;
}
 
CGetChar::CGetChar() :
m_flagStop(0)
{
}
 
CGetChar::~CGetChar()
{
}
 
int CGetChar::init(CALLBACK_GETCHAR callback)
{
        if(pipe(poll_getch)<0)
        {
                perror("pipe") ;
                return 1 ;
        }
 
        m_callbackGetChar = callback;
        pthread_create(&m_thGetChar, NULL,&threadGetChar, (void*)this) ;
        return 1 ;
}
 
int CGetChar::stop()
{
        m_flagStop = 1 ;
        int fd = poll_getch[0] ;
 
        if( fd>= 0)
                write(poll_getch[1],&fd, 1) ;
        return 1 ;
}
 
int CGetChar::destroy(void)
{
        int nStatus ;
        m_flagStop = 0 ;
 
        if(!m_flagStop)
        {
                int fd = poll_getch[0] ;
                if( fd>= 0)
                        write(poll_getch[1],&fd, 1) ;
                m_flagStop = 1 ;
        }
 
        pthread_join(m_thGetChar, (void**)&nStatus) ;
        return 1 ;
}
 

 

############# main.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
#include<cstdio>
#include<unistd.h>
#include "getChar.h"
#include<termio.h>
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
static char m_char ;
 
void cbGetChar(char ch)
{
        m_char = ch ;
        printf("ch : %c\n", m_char) ;
}
 
int main()
{
        CGetChar getChar ;
        getChar.init(&cbGetChar) ;
 
        while(1)
        {
                if(m_char == 'q')
                {
                        getChar.stop() ;
                        break ;
                }
                usleep(1000) ;
        }
 
        getChar.destroy() ;
        usleep(1000) ;
        return 1 ;
}
 

첨부파일 : getChar.zip

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4E4A12146415739A07C68401
원문 작성일 : 2011.08.16

------------------------------------------------------------------------

 

아래 테스트는 리눅스 환경에서 테스트하였습니다.
C++ 에서 작성된 myList.h, myList.cpp 라는 파일이 있다고 가정합니다.
c 로 작성된 main.c 파일이 있습니다.

main.c 가 myList.h 파일을 include 하여 해당 기능을 수행할 수 있도록 함이 목적입니다.
어떤 C++ 코드를 하나 만들어 봅니다.
C 에서의 사용을 고려하지 않은 C++ 코드는 아래와 같습니다.

 

=================================== myList.h

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _MYLIST_H_
#define _MYLIST_H_
 
#include<list>
using namespace std ;
 
typedef list<int>MyList ;
typedef list<int>::iterator MyListIter ;
 
class CMyList
{
public :
        int addList(int val) ;
        int getSize() ;
 
 
private :
        MyList m_list ;
        MyListIter m_listIter ;
};
 
#endif // _MYLIST_H_
 

 

======================================= myList.cpp

 
1
2
3
4
5
6
7
8
9
10
11
12
#include "myList.h"
 
int CMyList::addList(int val)
{
        m_list.push_back(val) ;
        return 1 ;
}
 
int CMyList::getSize()
{
        return m_list.size() ;
}

 

위 코드를 gcc로 컴파일하면 당연히 에러가 나겠죠.

아래와 같이 C 에서 컴파일할 수 있도록 작업을 해 줍니다.

 

1. C++ 전용(?) 코드는 #ifdef __cplusplus 로 막아줍니다.
   위 코드에선 STL 선언부랑 클래스 선언부가 해당될 겁니다.

2. C 에서 호출할 수 있도록 함수를 추가하여줍니다.
   int MyList_addList(int val) ;
   int MyList_getSize() ;

3. 구현부에서 name magling 이 안일어나도록 extern "C" 를 선언해 줍니다.
   위 조건대로 수정하면 아래와 같이 수정될 것입니다.

=============================================== myList.h

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
#ifndef _MYLIST_H_
#define _MYLIST_H_
 
#ifdef __cplusplus
 
#include<list>
 
using namespace std ;
 
typedef list<int>               MyList ;
typedef list<int>::iterator     MyListIter ;
 
class CMyList
{
public :
        int addList(int val) ;
        int getSize() ;
 
private :
        MyList m_list ;
        MyListIter m_listIter ;
};
 
#else
 
void* MyList_getInstance() ;
 
int MyList_addList(void* instance, int val) ;
int MyList_getSize(void* instance ) ;
 
void TEST_destory(void* instance) ;
 
#endif
#endif // _MYLIST_H_

 

================================================= myList.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
#include "myList.h"
 
int CMyList::addList(int val)
{
        m_list.push_back(val) ;
        return 1 ;
}
 
int CMyList::getSize()
{
        return m_list.size() ;
}
 
extern "C"
{
 
void* MyList_getInstance()
{
        CMyList* myList= new CMyList ;
        return (void*)myList ;
}
 
int MyList_addList(void* instance, int val)
{
        CMyList * myList = (CMyList*)instance ;
        myList->addList(val) ;
 
        return 1 ;
}
 
int MyList_getSize(void* instance )
{
        CMyList* myList = (CMyList*)instance ;
        return myList->getSize() ;
}
 
int MyList_destroy(void* instance)
{
        CMyList* myList = (CMyList*)instance ;
        delete myList ;
}
 
}

 

이제 C 전용(?)으로 선언된 아래 함수를 가지고 main.c 에서 써먹어 봅니다.

void* MyList_getInstance() ;
int MyList_addList(void* instance, int val) ;
int MyList_getSize(void* instance ) ;
void TEST_destory(void* instance) ;

=============================================== main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include "myList.h"
 
int main()
{
        void* myList = MyList_getInstance() ;
        int size = 0;
 
        MyList_addList(myList, 3) ;
        MyList_addList(myList, 8) ;
 
        size = MyList_getSize(myList) ;
 
        printf("size : %d\n", size) ;
 
        MyList_destroy(myList) ;
        return 1 ;
}

 

C++ 의 클래스 객체를 void* 로 대체하였습니다. 핸들처럼요.
C 나 C++ 컴파일러는 object 파일을 생성하는데 이 object 파일은 C, C++ 모두 공통으로 사용할 수 있습니다.
그래서 위와같이 살짝 수정하여 서로 호출이 가능할 수 있습니다.

정리하면,

1. 헤더파일의 C++ 코드는 C 컴파일러가 안보이도록 막고,
막은 부분을 대처할 수 있는 함수를 만들어줍니다.
#ifdef __cplusplus 부분이 이에 해당합니다.

2. C++ 컴파일러는 함수 오버로딩 때문에 함수 이름을 변경하여 object 파일을 생성합니다.
(Name mangling 관련 부분은 여기서 자세히 언급하지 않겠습니다.)
하지만 C 컴파일러는 함수 오버로딩을 지원하지 않습니다.

예들 들어,

test()

란 함수가 있다고 하면,
이를 C++ 컴파일러로 컴파일하면


testzx6e()

->이런식으로 변경되어 object 파일에 저장됩니다.

C 컴파일러로 컴파일하면

test()

그대로 저장됩니다.

즉, C 컴파일러는 사용자가

test()

라고 호출하면 object 파일에서 직관적으로

test()

를 찾습니다.

그런데 만약 object 파일을 C++ 컴파일러로 컴파일했다면...

test()

함수가

testzx6e()

로 저장되어있기에 C 컴파일러는


testzx6e()

->이 함수를 못찾겠죠.

이 때 사용하는 방법이, C++ 컴파일러에게, 이 파일들은 C 에서 사용될 예정이니
name mangling 을 수행하지 마라, 즉 object 파일 생성 시,


test()

test()

로 저장하라고 알려주는거죠.

이게 myList.cpp 의

extern "C"

부분입니다.

C++ 코드는 object 로 먼저 생성을 해야 C 에서 사용할 수 있습니다.
이제 마지막으로 Makefile 을 작성합니다.
최종 실행파일 생성 시, -lstdc++ 하는 부분에 주의합니다.
================================================= Makefile


main : myList.o main.c

        gcc -o $@ $^ -lstdc++


myList.o : myList.cpp

        g++ -c -o $@ $^


clean :
        rm -rf *.so *.o


=====================================================

-lstdc++ 부분은 아래 홈페이지에서 정보를 얻었습니다.
아래 분께서는 저와는 다른 방법 (구조체를 클래스처럼 쓰셨네요.) 으로
C에서 C++ 을 호출하고 계시니 참고하여 읽어보시기 바랍니다.


http://ospace.tistory.com/215

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4DE5F25DCB15739A07C68401
원문 작성일 : 2011.06.01
------------------------------------------------------------------------

 

Only C 로 코딩하다 보면 STL 의 컨테이너가 그리울 때가 있습니다.
C++ 로 컴파일해서 오브젝트 파일만 C 에서 갖다 써도 되긴 하지만...

그래서 검색해 봤더니...
역시나 나같은 사람이 있더군요. ㅋㅋ

http://kldp.org/node/112635 - "C++ 에서의<map>을 c 에서 사용하는 방법이 있나요?"
위 글을 통해 SCL (Small Container Library ) 이란 라이브러리를 알게 되었습니다.

홈페이지는 아래와 같습니다.
http://sourceforge.net/projects/libscl/

파일을 받아 압축을 풀면 안에 User Guide 를 통해 자세한 정보를 얻을 수 있습니다.
Hash, List, Map, Queue, Stack, Symbol (이건 뭐지? ), Tree, Vector 등의 함수를 제공합니다.
형식은 STL 의 그것과 꽤 흡사합니다.
예제도 풍부하니 쓰기에 어려움이 없을 것입니다.
그럼, 즐거운 하루 되세요.

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4DE5EF53C715739A07C68401
원문 작성일 : 2011.06.01
------------------------------------------------------------------------

 

첨부파일 : abstractFactory_by_c.zip

 

이게 다형성이라는 의미가 맞는건지 모르겠습니다.
차라리 디자인 패턴의 abstract factory 에 더 가까운 것 같기도 하고...
둘 다인가? ㅡㅡa

암튼, 제 의도는 아래와 같습니다.
제품을 만들다보면 어떨 땐 Intel 칩을 쓰기도 하고 어떨 땐 Broadcom 칩을 사용할 때도 있습니다.
비록 칩은 다르더라도 Chip_open(), Chip_read(), Chip_write(), Chip_close() 라는 공통 분모가 있습니다.

다시 얘기하면,
UI 개발자는 Intel 칩이든 Broadcom 칩이든 신경 안쓰고 저 4개 함수만 호출하면 되도록 짜고싶은거지요.

UI 에서 Chip_open(), Chip_read(), Chip_write(), Chip_close() 를 호출했을 경우,

Intel칩이라면 최종적으로 아래 함수가 호출되고,
INTEL_Chip_open(), INTEL_Chip_read(), INTEL_Chip_write(), INTEL_Chip_close() 가 호출되고,

Broadcom 칩이라면 최종적으로 아래 함수가 호출되도록 하는겁니다.
BROADCOM_Chip_open(), BROADCOM_Chip_read(), BROADCOM_Chip_write(),BROADCOM_Chip_close()

C++ 에서는 순수가상함수와 다형성을 이용하여 구현할 수 있습니다.
C 에선 함수포인터를 이용하여 비슷하게 구현할 수 있더군요. 형태 기록차원에서 초 간단하게~~
main.c 에서 Chip_open(), Chip_read(), Chip_write(), Chip_close() 가 호출되어집니다.
또한 main.c 가 바라보는 건 chip.h 만 바라봅니다.
chip.c 에서 어떤 칩을 사용할 것인지 결정하고, 그 결정에 따라 Intel 또는 Broadcom 의 함수포인터를
넘겨줍니다.

 

코드 분량을 최소화 했으니 보시는데 어려움이 없을 겁니다.

첨부파일 : abstractFactory_by_c.zip

 

map 컨테이너를 이용해 클래스 멤버함수의 콜백함수 등록과 호출하기.

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

 

원문 : http://cy.cyworld.com/home/21147242/post/4D75C4B98555739A07C68401
원문 작성일 : 2011.03.08

--------------------------------------------------------------------------------------------------------------


제목 참 거창하네...
일하다가 번뜩 떠올라 짜봤습니다.
map 컨테이너를 이용해 등록된 콜백함수를 좀 더 빠르게 찾지 않을까 하는 기대감입니다.
등록되는 콜백함수는 일반함수가 될 수도 있으나 클래스 멤버함수도 등록될 수 있음을 보였습니다.
클래스 멤버함수와 함수포인터의 관계는 데브피아 강의에 잘 나와있습니다. (아래 링크 참조)


http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=7431&ref=7431


아래와 같이 구상하고 흐믓해하며 자만심에 잠깐 빠져있다가
누군가도 나와같은 생각을 했을텐데.... 하고 검색해 봤습니다.
역시나... 기는 놈 위에 나는 분 계시더군요.
template 을 이용해 일반화까지 구현하여 블로그에 올리신 분이 계시더군요.
클래스 멤버함수 콜백 : http://blog.naver.com/yiyousung?Redirect=Log&logNo=80113313235
아래는 허접한 제 코드입니다.

 

 

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<cstdio>
#include<map>
 
using namespace std ;
 
enum Psi
{
        eDescVideo,
        eDescAudio,
        eDescSubtitle
};
 
class CPsiDescriptor
{
public :
        int switchDesc(Psi psi) ;
 
 
private :
        int descVideo(int a, int b) ;
        int descAudio(int a, int b) ;
        int descSubtitle(int a, int b) ;
};
 
typedef int (CPsiDescriptor::*FUNC_DESC)(int a, int b) ;
 
int CPsiDescriptor::switchDesc(Psi psi)
{
        static int flagSwitchDesc = 0 ;
 
 
        static map<Psi, FUNC_DESC>mapDesc ;
        static map<Psi, FUNC_DESC>::iterator mapDescIter ;
 
 
        static FUNC_DESC funcDesc ;
 
        if(!flagSwitchDesc)
        {
                mapDesc.insert(make_pair(eDescVideo,&CPsiDescriptor::descVideo)) ;
                mapDesc.insert(make_pair(eDescAudio,&CPsiDescriptor::descAudio)) ;
                mapDesc.insert(make_pair(eDescSubtitle,&CPsiDescriptor::descSubtitle)) ;
 
 
                flagSwitchDesc = 1 ;
        }
 
 
        mapDescIter = mapDesc.find(psi) ;
 
 
        if(mapDescIter != mapDesc.end())
        {
                funcDesc = mapDescIter->second ;
                (this->*funcDesc)(2, 3) ;
        }
        else
        {
                printf("cannot find PSI tags\n") ;
        }
 
 
        return 1 ;
}
 
int CPsiDescriptor::descVideo(int a, int b)
{
        printf("callback : descVideo()\n") ;
        return 1 ;
}
 
 
int CPsiDescriptor::descAudio(int a, int b)
{
        printf("callback : descAudio()\n") ;
        return 1 ;
}
 
int CPsiDescriptor::descSubtitle(int a, int b)
{
        printf("callback : Subtitle()\n") ;
        return 1 ;
}
 
int main()
{
        CPsiDescriptor psiDesc ;
 
        psiDesc.switchDesc(eDescVideo) ;
        psiDesc.switchDesc(eDescAudio) ;
        psiDesc.switchDesc(eDescSubtitle) ;
 
        return 1;
}
 

 

이글은 예전 싸이월드 블로그에 작성한 글을 가져온 것입니다.


원문 : http://cy.cyworld.com/home/21147242/post/4D75C4B98555739A07C68401

작성일 : 2011.03.08 

------------------------------------------------------------------------

아래 코드를 돌리면 무한루프에 빠집니다.

 #include<stdio.h>


int main()
{
     FILE* fp = fopen("FacotryStream.trp", "rb")
     unsigned char szBuff[1024] ;
     while(!feof(fp))
    {
          fread(szBuff, 4, 1, fp) ;
          fseek(fp, 184, SEEK_CUR) ;
     }
     printf("test finnish~~!!\n") ;
     return 1 ;
}



언뜻 보기엔 FILE 핸들을 받아 4Bytes 읽고 184Bytes 점프~

그러다 파일 끝에 도달하면 while() 문을 빠져나오는 것 같은데 말이죠.
핵심은 fseek() 함수입니다.
man fseek 해서 나오는 문구를 그대로 인용해보면,
"
fseek 함수의 연속적인 호출은 스트림을 위한 EOF 지정자를 지우고
.....블라블라블라~~"
그러므로 fseek() 함수 이후에 호출되는 feof() 함수는 무용지물이 된다는거죠.
위 코드의 while() 문은 아래와 같이 fseek 이전에 feof() 를 호출하도록 수정되어야 합니다.

while(1)
{
    fread(szBuff, 4, 1, fp) ;
    if(feof(fp))
        break ;
    fseek(fp, 184, SEEK_CUR) ;
}
그럼, 즐거운 하루 되세요.



이글은 예전 싸이월드 블로그에 작성한 글을 가져온 것입니다.


원문 : http://cy.cyworld.com/home/21147242/post/4C7DB9A7C7D5739A07C68401

작성일 : 2010.09.01 11:25


-----------------------------------------------------------------------

어떤 문자열이나 데이터에서 특정 비트열을 가지고 오고 싶을 때 사용하는
매크로 함수를 만들어 보았습니다.

PSI 데이터 parsing 하다가 만들게 되었네요.

buf 에 데이터를,
x, y 에 시작 비트열과 끝 비트열을 넣어주시면 됩니다.

맘대로 갖다 쓰셔도 되며 출처나 적어주심 감사하고~~
혹시나 버그 있을지 모르니 조심히... =_=;;

#define GETBIT_16(buf, x, y) (((unsigned short)(((0xFFFF>>((x) - 1)) \
                                                 ^ (0xFFFF>>(y))) \
                                                 &((unsigned short)(buf<<8) | ( *(&buf + 1))))) \
                                                 >>(16 - (y)))

#define GETBIT_8(buf, x, y) (((unsigned char)(((0xFF>>((x) - 1)) \
                                               ^ (0xFF>>(y)))&(unsigned char)(buf))) \
                                               >>(8 - (y)))

사용법.

unsigned char* szDATA ; // 데이터가 들어있는 변수.

11110011 01101100

위와같이 16개의 비트가 있을 때,

왼쪽에서 5번째부터 10번째까지 가져오고 싶다면~

GETBIT_16(*szDATA, 5, 10) ; // GETBIT_16(szDATA, 5, 10) 아님.

이렇게 사용하시면 됩니다.

출처 : http://jwmx.tistory.com/272

 

====================================

 

PuTTY와 TuTTY 모두 OpenSSH 서버로부터 만들어진 인증키를 이용하여 로그인할 수 있습니다. 또한 개인 키를 암호없이 만들면 암호 입력없이 로그인할 수 있습니다.
우선 텔넷으로 서버에 접속합니다. 인증키에 대한 암호를 입력해야 함으로, 당연히 ssh 를 이용한 텔넷을 이용하는 것이 안전하겠지요. ssh-keygen을 이용하여 ssh 인증키를 생성합니다.

인증키를 담는 파일 생성 위치와 파일 이름을 묻게 되는데, 기본 값을 사용하기 위해 엔터키를 누릅니다.

 

 

다음은 인증키를 보호하기 위한 암호를 입력할 차례입니다. 여기서 입력하는 암호는 인증키를 위한 암호이지 텔넷에 접속할 때 사용하는 암호가 아닙니다. 아래 글에서 PuttyGen을 사용하여 개인키를 만들 때 이해가 되실 것입니다.

 

 

 

암호 입력이 옳바른지 다시 한번 암호를 입력합니다.

 

 

 

아래와 같이 fingerprint까지 출력되었다면 정상 적으로 인증키가 만들어진 것입니다.

 

 

 

생성된 인증키 파일은 .ssh에 있습니다. .ssh로 이동합니다.

 

 

 

파일이 정상적으로 생성이 되었지요.

 

 

id_rsa는 개인키이고 서버에 접속하는 클라이언트쪽에서 필요한 파일입니다. id_rsa.pub는 공개키로 서버가 가지고 있어야 하는데, 파일 이름을 반드시

authorized_keys
로 변경해 주어야합니다.

 

 

 

텔넷이나 VNC나 SSH를 이용하여 프로그램이 (1) 서버에 접속하게 되면 (2) 프로그램은 개인키를 서버에 제시하게되고, (3) 서버는 .ssh 에 있는 authorized_keys 파일 값을 비교 확인하여 로그인을 허가하게 됩니다.

서버에서 할 일은 모두 끝났습니다.

 

이제 이 서버에 접속하려는 클라이언트쪽에서 해야할 일입니다

생성된 개인키, id_rsa를 ftp나 기타 방법으로 컴퓨터에 복사합니다. 이제 이 개인키를 가지고 PuTTY 나 TuTTY에서 로그인할 때 사용하는 인증키를 만들겠습니다.

 

PuTTY 홈페이지 의 다운로드 페이지 에서 PuTTYgen을 내려받습니다.
설치파일이 아니므로 바로 실행하시면 됩니다.
[Load] 버튼을 클릭합니다. 그리고 서버로부터 복사한 id_rsa 파일을 선택합니다.

 

 


그러면 암호를 물어 오는데, 인증키를 생성했을 때 사용한 암호를 입력합니다.

 


키를 이상없이 읽어 들였다면 아래와 같이 설명 글이 출력됩니다.

 

 

 

이제 텔넷 접속에 사용할 암호를 공백으로 수정해 줍니다. 개인키만 확인하면 로그인이 되도록 수정한다는 말씀이 되겠습니다.

 


화살표가 가르키는 암호를 모두 삭제합니다. 그리고 Save private key를 이용하여 적당한 곳에 개인키를 저장합니다.

 


이제 PuTTY나 TuTTY를 실행합니다. 이전 서버 접속에 대한 정보를 Load 합니다.



[Connection/Data]로 이동해서 로그인 ID를 입력합니다.



이제 [Connection/SSH/Auth]로 이동한 후 PuTTYgen에서 저장한 개인크를 선택하여 줍니다.

 


다음 사용을 위해 이 정보를 저장합니다.



이제 [Open]버튼으로 텔넷을 접속하여 보십시오. 이전과는 달리 암호 확인 없이 로그인이되지요.


PuTTYgen에서 만들어진 개인키는 매우 조심해야 합니다. 암호 확인 없이 텔넷에 접속할 수 있기 때문에 잘못 관리하셨다가는 큰 낭패를 보실 수 있습니다.

 

 

(작성일 : 2008.04.03, 티스토리로 이사하며 옮긴 글)

 

erase() 를 어케 써볼까 했더만,
찾아보니 간단한게 있네요. 쪼아~ ^^

 

======================================================
아쉽게도 VC++이나 Java에서 지원하는 trim() 함수가 STL String에는 없습니다. 따라서, 간단하게 아래 코드를 사용하시면 되겠습니다.

 

1. string의 왼편의 white space를 trim하고 싶은 경우
using namespace std;
string str("hello");
int n = str.find_last_not_of("tvn");
if ( n != string::npos )
str.replace(n+1, str.length()-n,"");
cout<<str;

 

2. string의 오른편의 white space를 trim하고 싶은 경우
using namespace std;
string str("hello");
int n = str.find_first_not_of("tvn");
if ( n != string::npos )
str.replace(0, n,"");
cout<<str;

 

3. string의 양쪽의 white space를 trim하고 싶은 경우
using namespace std;
string str("hello");
int n;
n = str.find_first_not_of("tvn");
if ( n != string::npos )
str.replace(0, n,"");
n = str.find_last_not_of("tvn");
if ( n != string::npos )
str.replace(n+1, str.length()-n,"");
cout<<str;

+ Recent posts