이제는 고인이 된 Gary mooore..
락블루스 음악의 거장..
고등학교때부터 수도 없이 들은 나의 전설..
그의 인생과 같은 음악을 하고 싶다.

환매
[경제] 증권회사 측에서 투자신탁의 중도 해약을 이르는 말
즉 환매란, 투자자가 이미 가입한 펀드 상품을 중도에 해지하고 입금한 돈을 찾아가는 것을 의미한다.



환매 수수료란?

펀드 상품도 특정 기간 내에 환매를 할 경우에는 환매수수료를 물어야 한다.
이는 투자자가 펀드에 돈을 넣은 지 얼마 되지 않아 별다른 이유없이 돈을 빼게되면,
펀드매니저의 자산 운용 계획에 차질이 생기게 되며, 이는 해당 펀드에 투자한 다른 투자자에게도
피해가 가게 된다. 따라서 일정기간은 돈 빼는 것을 자제해 달라는 뜻에서 소정의 페널티를 매기는 것이며,
이게 바로 펀드의 환매수수료 인 것이다. 여기서 일정 기간을 통상 "환매수수료 부과기간" 이라고 한다.
펀드 상품에 따라 다르지만 일반적으로,
가입한지 90일내 환매시 이익금의 70% , 180일 이내 환매시 50% 이런식으로 수수료를 부과하며,
펀드에 손실이 발생해서 환매를 할 경우에는 환매수수료를 떼지 않는다.
또한 이런 수수료는 펀드에 남아 있는 다른 투자자들에게 돌아가도록 만든다.



환매 수수료의 부과 방법
환매 수수료 부과 방법은 크게 정률제와 정액제 두가지 방법이 있다.
1. 정률제
- 중도환매를 할 때 자신이 벌어들인 펀드수익에 대해 일정한 비율로 수수료를 부과하는 방법이다.
ex) 90일 이내 환매시 이익금의 60%

2. 정액제
- 환매하려는 금액(좌수)을 기준으로 일정한 금액을 수수료로 빼내는 방법이다.
ex) 90일 이내 환매시 1000좌당 30원

이처럼 펀드에 수익이 많이 날 경우에는 정액제가 유리하다. 그러나 이런 환매 수수료에 얽매이기보다는
수익이 많이 나는 우량한 펀드를 고르는 것이 더 중요하다.



보통 환매했을 경우 주식형펀드의 경우, 4일이 걸리며, 채권형펀드의 경우에도 3일이 걸린다.
주식형인 경우 환매해줄 현금을 만들기 위해 펀드에 투자되어 있는 주식을 내다 팔아야 한다.
주식투자를 해본 사람은 알겠지만, 거래소는 3일 결제 시스템이며,
매매주문이 나간 날로부터 최종 주식과 현금이 결제되어 거래가 종료되는 데까지 3일이 걸린다.
이러한 시스템은 펀드에도 적용되며,
D일날에 환매요청을 받아 D+1 일에 금융기간이 해당 펀드에서 주식을 팔면,
그로부터 3일째인 D+3일에 돈이 들어오게 되는 것이며, 고객 입장에서는 환매요청일부터 4일이 걸린다.

채권형 펀드의 경우 D일에 환매요청이 들어오면 D+2 일의 가격을 기준가로 해서 그날(D+2) 돈을 내어주게 된다.
채권은 주식과 달리 당일 결제 시스템이기 때문이며, 고객 입장에서 환매요청일부터 3일이 걸리는 것이다.


'Investment > Fund' 카테고리의 다른 글

CD 와 CP, RP 란 무엇일까?  (0) 2011.07.24
채권이란 무엇일까?  (0) 2011.07.24
펀드란 무엇인가? ( 용어편 )  (0) 2011.07.18
펀드란,
어떤 목적을 달성하기 위해 모은 돈, 또는 그 돈이 모여 있는 서류상의 단체나 회사를 의미한다.
유네세프 (UNICEF) 또한 펀드라고 할 수 있다.
우리가 흔히 말하는 펀드란, 재테크를 잘 모르는 적은 돈을 가진 서민들의 돈을 모아
주식이나 채권, 부동산 같은 곳에 투자를 해서 생긴 수익으로 서민들의 자산을 증식시켜 줄 목적으로 만든 것이다.
물론 모든 펀드가 서민을 위한 것은 아니다. 사모펀드는 돈 많은 부자들 몇 명을 위한 펀드도 있다.
흔히 일반 서민사람들은 일반적인 펀드 ( 공모펀드 ) 를 어렵게 생각하는데, 사실 어려울 것이 없다.
단지 관련된 용어가 어려울 뿐이다. 밑에는 우리가 꼭 알아야 할 대표적인 용어들이다.


1. 좌수
- 펀드를 세는 단위이다.
- 예를 들어 1원에 하나씩 파는 펀드일 경우, 1000원을 입금했다면, 1000좌를 사는 것이다.
- 이 때 기준가는 1원이 되며, 편의상 1000좌를 기본으로 해서 그 단위를 나타내고 있다.
- 일반적으로 주식과 비교해 "주수" 와 같다고 생각하면 된다. 기준가는 "주가" 로 보면 될 것이다.




2. 펀드통장
펀드에 가입하면 통장을 받는다. 근데 이 통장은 우리가 생각하는 일반적인 예금 통장이 아닌,
펀드 증서의 보관대장쯤으로 생각하면 된다. 물론 요즘에는 실제 종이로 증서를 만드는 일도 거의 없어졌으며,
대부분 전산으로 입력해서 데이터로 보관한다. 펀드 통장에서 가장 중요한 것은 ,
좌수보다 평가금액이 크면 이득을 보고 있는 것이고, 좌수보다 평가금액이 작으면 손해를 보고 있다는 것이다.



3. 자산운용사
정부의 허락을 받은 금융회사를 지칭하며, 반드시 회사 이름을 지을 때 무슨무슨 자산운용 또는 무슨무슨 투자신탁 이라는
단어를 이름 끝에다 붙여야 한다. 또한 상시로 금융감독원 이라는 정부기관으로부터 관리 감독을 받아야 한다.
이는 엄격한 규정이며, 은행이나 증권사도 마찬가지이다.
펀드에 투자하게 되면 그 돈은 자산운용사에서 도맡아 운용을 하게 되며, 자산운용사에는 자산을 전문적으로
운용하는 전문가들이 있는데, 이들이 바로 펀드 매니저라고 불린다.
즉 자산운용사는 용병 부대이고, 펀드매니저는 용병인 셈이다.
하지만 정부에서는 하나의 금융회사가 혼자서 모든 일을 하지 못하도록 각각 필요한 역활들을 몇개로 나누었고,
이는 상호견제와 보완을 통해 더욱 더 투명하고 안전한 펀드자산 운용을 가능케 만들었다.


4. 운용회사 (자산운용사)
펀드 상품을 어느 주식, 어느 채권 등에 투자할지에 대한 운용 지시를 내리는 곳이다.

5. 판매회사
자산운용사가 운용하는 펀드 상품의 판매를 전담하는 회사다.
펀드를 투자하려면 자산운용사가 아닌 이 판매회사를 찾아가야 하며, 증권사, 은행 등이 여기에 해당한다.
참고로 삼성증권이든 어디든 단지 판매회사기 때문에, 실제 수익률을 높여주는 곳은 해당 펀드를 운용하는
자산운용사다. 그러므로 삼성증권에서 팔든 그렇지 않던 그게 중요한 게 아니라, 어떤 자산운용사가 운용하는
펀드인지가 중요하다.

6. 수탁회사
펀드의 돈을 보관하는 회사이며, 고객이 판매회사를 통해 펀드에 가입하면, 자신의 돈이 자산운용사로 가는 게 아니라
수탁 회사로 보내준다. 물론 수탁 회사 에서는 이 돈을 자신의 돈과는 분리해서 보관했다가,
자산운용사가 운용 지시를 내리면 그에 따라 주식이나 채권 등을 사기도 하고 파는 것이다.
스스로 의사 결정을 내려서 매매를 하지 않지만, 혹시 자산 운용사가 불법적이거나 터무니없는 운용지시를 내리면
이에 반발할 수도 있다. 은행이 주로 이런 수탁회사의 역활을 한다.

7. 사무관리회사
펀드 상품의 기준가를 계산하는 역활을 하며, 자산운용사의 지시에 따라 수탁회사에서 투자한 펀드자산에 대해 그 가치를
산정하여 기준가로 계산해 고객에게 알려준다. 즉 펀드통장을 찍어주는 일을 말한다.
펀드에 따라 독립적으로 사무관리회사를 두는 경우도 있으나, 자산운용사의 내부조직으로 운영되기도 한다.





'Investment > Fund' 카테고리의 다른 글

CD 와 CP, RP 란 무엇일까?  (0) 2011.07.24
채권이란 무엇일까?  (0) 2011.07.24
환매란 무엇일까?  (0) 2011.07.18

1. 윈도우 패스워드의 특성
- 기본적으로 윈도우의 패스워드 구조 자체가 취약하다.
- 윈도우 패스워드는 특이하게 패스워드의 길이에 관계없이 8바이트가 하나의 블록을 형성한다.
- 이 중 1바이트는 패스워드 블록에 대한 정보를 담고 있으므로, 실질적으로 패스워드 문자열을 저장하는 것은 7바이트다.
- 따라서 비밀번호가 qwer1234 일 경우 모두 8개의 문자이므로 두 개의 블록을 형성하게 된다.
- 지금까지 발매된 윈도우는 기본적으로 위와 같은 형태이며, 하나의 패스워드 블록은 별도로 운영된다.
- 따라서 하나의 패스워드 블록의 길이인 7 글자를 크래킹하는데 걸리는 노력이면, 아무리 긴 패스워드라도 풀 수 있는 것이다.
- qwer1234 일 경우 qwer123 과 4 로 저장이 되며, qwer123은 쉽게 크랙킹 하기 어렵겠으나, 뒤에 4 는 몇 초도 안되는 사이에 - 크래킹 할 수 있다. 그러므로 사실 상 7개의 글자나 8개의 글자나 패스워드의 강도는 같다고 봐도 무방하다.
- 즉 윈도우에서는 14개 문자 길이의 패스워드를 크래킹 하는 것은 7개의 패스워드를 2개 크래킹 하는 것이다.

하지만 다행히도 이러한 패스워드 강도는 공격자가 SAM 파일을 획득한 경우에만 해당되는 경우며,
원격에서 공격을 시도할 경우에는 윈도우에서도 리눅스처럼 글자수에 따라 강도가 커지게 된다.
SAM 파일을 획득해야만 7글자의 패스워드 블록 단위로 패스워드 크래킹이 가능하기 때문이다.


- 윈도우 패스워드 크래킹을 위한 툴
1. NAT ( NetBIOS Auditing Tool )
- nat -u userlist.txt -p dic.txt "ip주소"

2. pwdump3
 pwdump3 "\\아이피주소" sam_file administrator

3. LC4
- GUI 툴이며, import -> import From PWDUMP File 메뉴에서 사용한다.



'Hacking > System Hacking' 카테고리의 다른 글

윈도우의 인증 구조  (0) 2011.07.18
파일시스템 : FAT 과 NTFS  (0) 2011.07.18
윈도우의 주요 서비스  (0) 2011.07.18
윈도우의 부팅 순서  (0) 2011.07.16
윈도우 2000의 인증 과정에서 가장 중요한 구성 요소는 다음과 같다.

- LSA ( Local Security Authority )
- SAM (Security Accounts Manager )
- SRM ( Security Reference Monitor) 
LSA 
- 모든 계정의 로그인에 대한 검증을 하고, 시스템 자원 및 파일 등에 대한 접근 권한을 검사한다.
- 로컬, 원격 모두에 해당하며, SRM 이 생성한 감사 로그를 기록하는 역활도 한다.
- NT 보안의 중심 요소이며, 보안 서브 시스템 이라고 부르기도 한다.

SAM
- 사용자/그룹 계정 정보에 대한 데이터베이스를 관리한다. 사용자의 로그인 입력 정보와 SAM 디비 정보를 비교하여
- 인증 여부를 결정하도록 해주는 것이다.
- 보통 SAM 파일은 \system32\config\sam 에 위치하며, 이 파일은 시스템을 부팅시킨 경우
- 접근 제한으로 읽을 수 없는 파일이다.
- 하지만 윈도우에서는 SAM 을 이용한 인증이 모두 같은 것이 아니며, 다음의 세 가지로 나뉘게 된다.

1. LM ( Lan Manager )
윈도우에서 가장 약한 인증 방법이다. 랜에서 파일을 공유하기 위해 사용하는 인증 방법으로
윈도우 XP 이하 버전에서 사용하며, 크래킹하는데 10초도 걸리지 않는다.

2. NTLM ver1 
LM 보다는 안전하나 취약점이 발견되어 오래 적용되지 않았다.

3. NTLM ver2
윈도우 XP와 2000의 시스템에 적용되어 있다.

NTLM 은 인증에 도전/응답 (Challenge / Response )  방식을 사용한다.
이러한 인증법을 사용하는 이유는 네트워크에 패스워드를 흘려보내지 않고 인증을 성공시키기 위해서다.
유닉스의 텔넷과 같은 경우, 기본적으로 네트워크에 패스워드를 보내는데 이는 매우 취약하기 때문이다.


SRM
- SAM 이 사용자의 계정과 패스워드가 일치하는 지를 확인하여 SRM 에게 알려주면 SRM 은 사용자에게
- 고유의 SID 를 부여한다. 또한 SRM 은 SID에 기반하여 파일이나 디렉토리에 접근 제어를 하게 되고, 이에 대한
- 감사 메시지 또한 생성한다.

SID
- SRM 이 할당해준 SID 를 윈도우 2003에서는 whoami user/SID   명령을 이용해 간단히 알아 볼 수 있었으나,
- 윈도우 2000과 XP 에서는 윈도우 리소스 킷의 getsid 란 툴을 이용해야 한다.
- 사용법은 cmd 창에 getsid 명령을 명령 프롬프트에서 실행하면 된다.
- getsid 툴은 기본적으로 설치되어 있지 않으므로 따로 구해서 사용해야 한다.



'Hacking > System Hacking' 카테고리의 다른 글

윈도우의 패스워드 구조  (0) 2011.07.18
파일시스템 : FAT 과 NTFS  (0) 2011.07.18
윈도우의 주요 서비스  (0) 2011.07.18
윈도우의 부팅 순서  (0) 2011.07.16

FAT ( File Allocation Table )

FAT 은 기본적으로 16 비트 크기의 테이블을 가지고 있으며, 하나의 클러스터는 32 KB 이므로 전체 가능 용량은
2GB 이다. (2 * 1024 * 1024 * 1024 Byte )

이후 FAT 의 최대 용량의 한계가 지적이 되자 FAT 32가 개발이 되었고, 이 후 윈도우95 OSR2에서 처음 도입되어 사용되었다.
FAT32 는 총 32 비트 개수만큼의 클러스터를 가질 수 있었으므로 FAT 과는 비교할 수 없을만큼 큰 용량이 가능해졌다.
현재도 FAT32는 USB 에 종종 사용되는데, 이는 호환성이 좋은 편이어서 윈도우에서 리눅스나 리눅스에서 윈도우로 파일을 옮길 때 유용하게 쓰인다. 그러나 보안 관점에서 NTFS 처럼 접근 제어를 설정할 수 없으므로 보안에 많이 취약하다.

이후 NTFS는 FAT 과 OS/2 의 파일 시스템이었던 HPFS 의 장점을 모아 만든 것이며, 윈도우 2000부터 적용되었다.
NTFS는 아주 다양한 기능을 가지고 있으며, 윈도우 NT 계열의 운영체제에서만 사용할 수 있다.
물론 리눅스에서 마운트하거나 부팅 디스켓을 이용하여 읽을 수는 있으나 쓰기는 불가능하다.
이런 점은 호환성에 문제가 있어 보이나, 보안에서는 굉장히 중요한 사항이다. 또한 NTFS 는 파일 시스템의 결함 관리에 있어,
FAT이나 FAT32 보다 훨씬 좋은 성능을 보여주는데, FAT 이나 FAT32 경우 , 파일 시스템에 문제가 생길 경우
파일 이름이 깨지거나 폴더 구조가 이상하게 된다. 이러한 문자게 생기면 디스크 도구에서 에러 검사를 수행해주어야 했다.
그러나 NTFS를 사용한다면 디스크 에러 검사를 수행할 일은 거의 없다.
NTFS 는 갑작스런 전원의 차단에도 하드디스크의 사용에 대한 자신의 로그를 따로 기록하여 스스로 복구하는 기능이 있다.
안전성면에서도 FAT, FAT32를 능가한다.

보안 관점에서도 NTFS는 개별적인 폴더와 파일에 대해 사용 권한을 설정할 수 있고, 각 파일과 폴더에 해당 계정만이 접근하여 읽을 수 있도록 암호화할 수도 있다. 폴더를 암호화하면 그 안 내용도 모두 암호화된다.
이렇게 암호화된 폴더나 파일은 복사나 이동을 해도 암호화된 속성이 사라지지 않으며, 파일 단위로 어떤 계정을 가진 사람이
어느날 몇시 몇분에 파일을 열어보거나, 열려다 실패했는지도 알 수 있는 감사 (auditing) 기능이 있다.

또한 파일이나 폴더 별로 압축하여 관리할 수 있으며, 재부팅하지 않고 파티션을 변경할 수도 있다.
그러나 운영체제를 구동중인 파티션은 예외다. 그리고 쿼터 기능도 지원하는데 기본적으로 4개까지 파티션 지원이 가능하다.
파티션은 크게 기본 파티션(Primary) 와 확장 파티션 (Extended) 으로 나뉘는데, FAT 에서는 기본 파티션을 하나만
설정할 수 있는데 반해, NTFS 는 3개까지 설정이 가능하다.
확장 파티션은 다시 몇개의 파티션으로 나눌수도 있다.
이렇듯 많은 기능을 가진 NTFS의 단점은 하나의 파일이 가져야 할 정도가 그만큼 많아 지므로, 오버헤드가 크다.
오버헤드는 하나의 파티션에 5MB 정도이며, NTFS로 포멧시 하드 디스크의 용량 중에 5MB 는 사라지게 된다.

'Hacking > System Hacking' 카테고리의 다른 글

윈도우의 패스워드 구조  (0) 2011.07.18
윈도우의 인증 구조  (0) 2011.07.18
윈도우의 주요 서비스  (0) 2011.07.18
윈도우의 부팅 순서  (0) 2011.07.16


중지하면 안되는 주요 서비스들

1. Network Connections
- 시스템에 관련된 모든 네트워크 및 전화 접속 연결에 대한 서비스를 제공하며, 상태를 표시한다.
이 서비스를 중지 시킬 경우 네크워크에 대한 모든 접속이 불가능해진다.

2. Plug and Play
- 하드웨어에 대한 자동 인식과 설정을 도와주는 서비스이며, 중지시킬 경우 시스템이 불안정해진다.

3. Security Accounts Manager  (SAM)
- 인증에 관련된 서비스로 중지시킬 경우 다른 시스템이 해당 시스템에 접근할 수 없게 된다.

4. Windows Management Instrumentation ( WMI )
- 시스템의 관리 정보를 제공하는 서비스다. 응용 프로그램과 서비스가 생성하는 관리 이벤트를 포함하여
응용 프로그램 서비스에 접근 정보를 제공한다. 또한 SNMP 와도 호환된다.

5. Application Management
- 응용 프로그램의 설치, 제거와 같은 서비스를 제공하며, 중지시킬 경우 응용 프로그램을 추가/삭제하지 못한다.

6. Remote Procedure Call ( RPC )
- RPC 에 관련된 서비스를 제공한다. 서비스를 끄면 해당 컴퓨터가 부팅되지 않는다!!

7. Server
- RPC 지원 및 파일, 인쇄 등을 위한 자원 공유를 제공한다.




다음은 선택 사항의 서비스들에 대해 알아보자.

1. COM+ ( an extension to the Component Object Model) Event System
- COM 은 프로그램의 컴포넌트 객체들을 개발하고 지원하기 위한 하부 기반 구조로, COBRA ( Common Object Request Broker Architecture ) 에서 정의된 수준의 기능 제공을 목표로 한다. 마이크로소프트의 OLE 가 사용자가 화면에서 볼 수 있는 복합 문서를 위한 서비스를 제공하는 반면에, COM 은 인터페이스 교섭과 언제쯤 객체가 시스템에서 제거될 수 있는지를 판단하며, 라이센스 및 이벤트 서비스 등을 제공한다. COM+ 는 이러한 COM 구성요소에 이벤트를 자동으로 배포한다. COM + 이벤트는 COM + 프로그래밍 모델을 확장하여 게시자/가입자와 이벤트 시스템 사이의 이벤트나 메소드 호출을 지원한다.

2. Computer Browser
- 네트워크에 있는 컴퓨터의 최신 목록을 유지하고, 요청하는 프로그램에게 목록을 제공한다.
이 서비스는 네트워크 도메인과 리소스를 보아야 할 윈도우 컴퓨터에게 사용한다. 브라우저로 지정된 컴퓨터는 해당 네트워크에서 사용되는 모든 공유 리소스를 포함하는 찾아보기 목록을 유지한다.

3. Distributed Link Tracking (DLT) Client
- 네트워크 도메인의 여러 컴퓨터에 걸쳐 있거나, 하나의 컴퓨터에 있는 NTFS 파일 시스템 사이의 링크를 유지 및 관리한다.
DLT 클라이언트 서비스를 사용하면 대상 파일의 이름이 바뀌거나 이동 된 후에도 바로 가기와 OLE 링크가 계속 작동한다.

4. File Replication
- 자동 파일 복제 서비스다. 여러 서버에 존재하는 파일을 복사 및 관리하고 동기화 시켜준다.
또한 내결함성이 있는 DFS ( Distributed File System )과 관련된 대체 대상 사이에서 파일을 동기화하도록 이 서비스를 구성할 수 있으며, 도메인 컨트롤러의 경우 이 서비스를 중지시킬 경우 심각한 손상이 발생할 수 있다.

5. Internet Authentication Service ( IAS )
- VPN , RAS 장비 또는 무선 및 LAN, WAN 네트워크에 접속하는 사용자의 인증, 권한 부여, 감사 및 계정 작업을 수행한다.

6. Intersite Messaging (ISM)
- 윈도우 서버간에 메시지를 주고 받을 수 있다.



'Hacking > System Hacking' 카테고리의 다른 글

윈도우의 패스워드 구조  (0) 2011.07.18
윈도우의 인증 구조  (0) 2011.07.18
파일시스템 : FAT 과 NTFS  (0) 2011.07.18
윈도우의 부팅 순서  (0) 2011.07.16
1. POST (Power On Self Test)
- POST 란, 운영체제와는 상관없이 하드웨어 자체가 시스템에 문제가 있는지 체크하는 과정이다.
BIOS 에 의해 실행되며, 라우터나 스위치, 브릿지 등도 처음 켜면 POST 를 실시한다.
POST 도중 하드웨어에 문제가 발견되면 여러 방법으로 문제를 알리는데, 예를 들면
그래픽 카드를 제대로 설치하지 않거나, 접촉 불량이 있을 경우 삐삑~ 하는 경고음을 말한다.
이런 경고음은 POST 에 의해서 만들어진다. 문제에 따라 경고음의 횟수와 음의 길이가 다르므로
경고음만 들어도 어디에 문제가 있는지 판단할 수 있고, 요즘에는 메인보드의 LED 를 이용해 표시한다.


2. CMOS ( Complementary Metal - OXide Semiconductor )
- BIOS 와 거의 같다고 보면 된다.


3. MBR  ( 마스터 부트 레코드 )
- CMOS 정보를 읽어 부팅 매체를 확인한 뒤, 부팅 매체의 MBR 정보를 읽는데,
MBR에는 부팅 매체에 대한 기본적인 파일 시스템 정보가 들어있다. MBR 정보는
운영체제가 부팅된 뒤에는 편집할 수 없으며, 접근할 수도 없다.
윈도우 2000이 설치되어 있을 경우 MBR에는 NTLDR 의 위치정보를 담고 있다.
그러나 반드시 필요한 것은 아니며, C 드라이브에 운영체제를 기본 설정대로 설치했다면,
MBR이 삭제되어도 문제가 생기지 않는다.

4. NTLDR
- 하드디스크의 부팅 파티션에 있는 프로그램으로, 부팅될 수 있도록 간단한 파일 시스템을 실행하며,
boot.ini  파일의 내용을 읽어 가능한 부팅 옵션을 보여준다.



5. NTDETECT.com
- NTDETECT  는 NTLDR 로부터 제어권을 위임받아 시스템에 설치된 하드웨어를 검사한다.
- 다음은 NTLDR 이 검사하는 하드웨어다.

  • PC의 컴퓨터 CPU 유형
  • 버스유형
  • 비디오 보드 유형
  • 키보드와 마우스 종류
  • 컴퓨터에 장착되어 있는 직렬 포트와 병렬포트
  • 플로피 드라이브

NTDETECT 가 문제없이 작동하면 레지스트리에 하드웨어 키를 만드는데, 이 키는 HKEY_LOCAL_MECHINE 에 있다.
컴퓨터를 부팅할 때마다 레지스트리의 해당 부분이 만들어지기 때문에 항상 현재의 하드웨어 구성을 반영하게 된다.


6. ntoskrnl.exe (NT OS Kernel)
- ntoskrnl 은 Hardware Abstraction Layer (HAL.DLL) 을 로드한다.
- 다음은 4단계의 로드 단계다.

(1) 커널 로드 단계
- 운도우 2000은 시스템 설정을 로드하고, 이것을 HKEY_LOCAL_MACHINE\System\CurrentControlset\Services 에 저장한다.
윈도우 2000은 이 정보를 확인하고 로드할 드라이브와 그 순서를 결정한다.

(2) 커널 초기화 단계
- 드라이버에 대한 현재의 제어 세트를 검사하고 작업을 시작한다.

(3) 서비스 로드 단계
- Session ManagerSubSystem(smss.exe)와 Win32 서브 시스템을 로드한다.

(4) 서브시스템 시작 단계
- 윈도우 서브시스템이 초기화된다. Win32 서브 시스템은 로그인에 대한 처리를 하고 winlogon.exe 를 시작한다.
- 컨트롤 + 알트 + DEL 키를 누르면 로그인 창이 활성화되고, 계정과 패스워드를 입력받아 로컬 보안 인증서버
(lsass.exe) 에 보낸다. 로컬 보안 인증 서버는 보안 계정 관리자( SAM) 에 저장되어 있는 정보와 비교하여
일치하면 userinit.exe 프로세스가 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogn 의 셀 값에서 참조되는 셸을 실행한다.


이상 윈도우의 부팅 과정에 대해 알아보았다.











  1. 운영체제를 선택하는 화면에서의 대기시간을 말한다. 30초 동안 입력하지 않으면 밑에 명시되어 있는 default 로 운영체제를 부팅한다. [본문으로]
  2. multi(0) = E-IDE 컨트롤러를 가지는 디스크임을 나타내며, SCSI 컨트롤러에 부착된 디스크에서 부팅시 mult(0) 대신에 scsi(0) 를 쓰게 된다. 숫자 0은 첫 번째 컨트롤러 임을 나타낸다.disk(0) 는 scsi로 시작할 경우에 rdisk(0)은 IDE,E-IDE,SCSI with BIOS 방식의 디스크에 해당하는 표현이다.마찬가지로 0은 해당 컨트롤러에서 첫번째 임을 말하고, partition(3)은 파티션의 순서를 나타내며, 이 값은 0이 아닌 1부터 시작한다.partition(3) 이므로 디스크의 세 번째 파티션에 운영체제가 있음을 나타낸다. [본문으로]

'Hacking > System Hacking' 카테고리의 다른 글

윈도우의 패스워드 구조  (0) 2011.07.18
윈도우의 인증 구조  (0) 2011.07.18
파일시스템 : FAT 과 NTFS  (0) 2011.07.18
윈도우의 주요 서비스  (0) 2011.07.18

1. SBCS ( Single Byte Character Set )

문자를 표현하는데 있어서 1바이트만을 사용하는 방식으로, ASCII 코드가 대표적이다.


2. MBCS ( Multi Byte Character Set )

동일한 바이트 수로 문자를 표현하는게 아니라 , 다양한 바이트 수를 사용해서 문자를 표현하는 방식이다.
예를들면 어떤 문자는 1바이트로 표현하고 어떤 문자는 2바이트로 표현한다.
MBCS는 SBCS를 포함하는데, 대부분의 문자들을 2바이트로 처리하되, 아스키코드에서 정의하고 있는 문자를
표현할 때는 1바이트로 처리한다. 즉 MBCS 에서는 영어는 1바이트로, 한글은 2바이트로 처리한다.
굉장히 효율적인 방법이라 생각할 수 있지만, 구현하기에는 굉장히 까다롭다.


3. WBCS ( Wide Byte Character Set )

모든 문자를 2바이트로 표현하는 문자셋이다.
대표적으로 유니코드가 WBCS 에 해당하며, 유니코드 기반 문자열이라고도 한다.



WBCS 기반의 프로그램을 만들기 위해서는 몇 가지 중요한 점이 있다.

1.  char - > wchar_t
- 문자를 표현하는데 사용되는 자료형 char 를 대신해서 자료형 wchar_t 를 사용한다.
- char은 1바이트 메모리 공간만 할당되지만, wchar_t 는 2바이트 메모리 공간이 할당된다.
- 따라서 유니코드 기반의 문자표현이 가능하다.
- typedef unsigned short wchar_t

2. ABC  ->   L"ABC"
- wchar_t str[] = "ABC"  로 할 경우 오류가 생기는데, wchar_t 는 유니코드 문자형식이지만
- 오른쪽 "ABC" 는 MBCS 기반이기 때문이다. 그러므로 다음 형태로 바꿔줘야 한다.
- wchar_t str[] = L"ABC"
- 여기서 L 은 다음에 나오는 문자열을 유니코드 기반으로 표현하라는 의미이다. 널 문자도 2바이트로 처리되므로 총 8바이트!

3.  strlen  -> wcslen
- strlen 은 SBCS 기반이므로 wcslen 으로 (WBCS 기반) 으로 바꿔서 사용해야 한다.
- 사용법이나 전달인자의 개수 등은 완전히 동일하므로 어려울 것은 없다.


 SBCS 기반 함수  WBCS 기반 함수
 strlen  size_t [각주:1] wcslen
 strcpy  wcscpy
 strncpy  wcsncpy 
 strcat  wcscat 




4. 완전한 유니코드 기반 (1)

윈도우 2000 이상의 운영체제에서는 이제 기본적으로 유니코드를 지원하며, 내부적으로도 모든 문자열을 유니코드
기반으로 처리한다. 그러므로 유니코드 기반으로 프로그램을 작성하지 않는다면 성능에 영향을 미칠 수 있다.

wprintf( L"Hello World");

위 문장은 printf 함수의 유니코드 버전이며, 다음은 문자열 입출력 함수 중 WBCS 기반의 예이다.
 SBCS 기반 함수  WBCS 기반 함수 
 printf  int wprintf 
 scanf  int wscanf 
 fgets  wchar_t * fgetws 
 fputs  int fputws 





5. 완전한 유니코드 기반 (2)

main  ->  wmain(int argc, wchar_t* argv[])

본래의 main 함수의 argv 는 char* 형식 (SBCS) 이고 argv[]를 wchar_t* argv[] 로 바꾸더라도 main함수는 실행 시 전달되는 문자열을 MBCS 기반으로 구성하기 때문에 엉뚱한 출력결과가 보일 것이다.
그러므로 유니코드 기반의 main함수를 사용해야 하는데 그것이 바로 wmain 함수이다.



  1. typedef unsigned int size_t [본문으로]

---------------------------클라이언트---------------------------------------------------
//데이터 통신에 사용할 변수
 char buf[BUFSIZE+1]; [각주:1]
 int len;[각주:2]

 while(1)
 {
  //데이터 입력
  ZeroMemory(buf, sizeof(buf));[각주:3]
  printf("\n[보낼 데이터]");[각주:4]
  if(fgets(buf, BUFSIZE+1, stdin) == NULL)[각주:5]
   break;[각주:6]
  //\n 문자 제거
  len = strlen(buf);[각주:7]  
  if(buf[len-1] =='\n')[각주:8]
   buf[len-1] = '\0';[각주:9]
  if(strlen(buf) == 0)[각주:10]
   break;[각주:11]

  //데이터 보내기[각주:12]
  retval = send(sock,buf,strlen(buf), 0);
  if(retval == SOCKET_ERROR)
  {
   err_display("send()");
   break;
  }

  printf("[TCP 클라이언트] %d 바이트를 보냈습니다! \n", retval);
  
  //데이터 받기[각주:13]
  retval = recvn(sock,buf,retval,0);
  if(retval == SOCKET_ERROR)
  {
  err_display("recv()");
  break;
  }
  else if(retval==0)
  break;

  //받은 데이터 출력
  buf[retval] = '\0';[각주:14]
  printf("[TCP 클라이언트] %d 바이트를 받았습니당! \n" , retval);
  printf("[받은 데이터] %s\n", buf);

 }
-----------------------------------------------------------------------------------


---------------------------서버-----------------------------------------------------
//여기서 사용한 소켓( client_sock ) 은 accept() 함수의 리턴값으로 생성된 것임을 유의하도록 하자.

char buf[BUFSIZE+1];[각주:15]
 //클라와 데이터 통신
 while(1)[각주:16]

 retval = recv(client_sock,buf,BUFSIZE,0);[각주:17]
 if(retval == SOCKET_ERROR)
 {
  err_display("recv()");
  break; 
 }

 else if(retval == 0)
 {
  break;
 }
 //받은 데이터 출력
 buf[retval] = '\0';[각주:18]
 printf("[TCP/%s:%d] %s\n",
  inet_ntoa(clientaddr.sin_addr),
  ntohs(clientaddr.sin_port ), buf);
 

 //데이터 보내기
 retval = send(client_sock,buf,retval,0);
 if(retval == SOCKET_ERROR)
 {
  err_display("send()");
  break;
 }
 }



  1. 입력 문자열 길이를 계산할 때 사용한다. [본문으로]
  2. fgets() 함수를 이용해 사용자로부터 문자열을 입력받는다. [본문으로]
  3. 사용자가 입력한 문자열 또는 서버로부터 받은 데이터를 저장할 버퍼다. [본문으로]
  4. 사용자가 입력한 문자열 또는 서버로부터 받은 데이터를 저장할 버퍼다. [본문으로]
  5. 사용자가 입력한 문자열 또는 서버로부터 받은 데이터를 저장할 버퍼다. [본문으로]
  6. 사용자가 입력한 문자열 또는 서버로부터 받은 데이터를 저장할 버퍼다. [본문으로]
  7. \n 문자를 제거한다.데이터 출력 시 줄바꿈 여부를 서버가 결정하도록 하기 위함이다. [본문으로]
  8. \n 문자를 제거한다.데이터 출력 시 줄바꿈 여부를 서버가 결정하도록 하기 위함이다. [본문으로]
  9. 글자를 입력하지 않고 엔터 키만 눌렀을 시 루프를 빠져나간다. [본문으로]
  10. \n 문자를 제거한다.데이터 출력 시 줄바꿈 여부를 서버가 결정하도록 하기 위함이다. [본문으로]
  11. \n 문자를 제거한다.데이터 출력 시 줄바꿈 여부를 서버가 결정하도록 하기 위함이다. [본문으로]
  12. send() 함수를 호출하고 오류 처리를 한다. 블로킹 소켓을 사용하므로 send() 함수의 리턴값은 strlen(buf) 값과 같게 된다. [본문으로]
  13. recvn() 함수를 호출하고 오류처리를 한다. 서버가 보낼 데이터의 크기를 미리 알고 있으므로 recvn() 함수를 사용하는 것이 편리하다. [본문으로]
  14. 받은 데이터 끝에 \0 을 추가하고 화면에 출력한다. [본문으로]
  15. 받은 데이터를 저장할 애플리케이션 버퍼다. [본문으로]
  16. recv() 함수를 호출하고 오류 처리 한다.서버는 받을 데이터 크기를 미리 알 수 없으므로 recvn() 함수를 사용할 수 없다. [본문으로]
  17. recv() 함수의 리턴값이 0 (정상종료) 또는 SOCKET_ERROR 가 될때까지 계속 루프를 돌며 데이터를 수신한다. [본문으로]
  18. 받은 데이터 끝에 \0 을 추가하고 화면에 출력한다. [본문으로]

'Windows > Network Programming' 카테고리의 다른 글

데이터 전송 함수 및 소켓 데이터 구조체  (0) 2011.07.16
TCP Client 분석  (0) 2011.07.15
TCP Server 분석  (0) 2011.07.15
TCP Server / Client  (0) 2011.07.15

데이터 전송 함수는 크게 데이터를 보내는 함수와 데이터를 받는 함수로 구분할 수 있다.
가장 기본이 되는 함수는 send()와 recv()이며, 그 밖에 WSA*() 형태의 확장 함수가 존재한다.

소켓 데이터 구조체란?
- TCP 소켓과 연간된 데이터 구조체로서, 각각 자신과 상대방의 IP 주소와 포트 번호 외에 데이터 송수신 버퍼가 있다.
송신 버퍼는 데이터를 전송하기 전에 임시로 저장해두는 영역이고,
수신 버퍼는 받은 데이터를 애플리케이션이 처리하기 전까지 임시로 저장해두는 영역이다.
송신 버퍼와 수신 버퍼를 통틀어서 소켓 버퍼라 부르며, send(), recv() 함수는 소켓을 통해 간접적으로 소켓 버퍼를
접근할 수 있도록 만든 함수라고 볼 수 있다.


데이터 전송 함수를 사용할 때는 하부 프로토콜의 특성을 잘 알고 있어야 하는데, TCP 프로토콜은 애플리케이션이 보낸
데이터의 경계를 구분하지 않는다는 특징이 있다. 예를 들어보면,
클라이언트가 100,200,300 바이트 데이터를 차례로 보낼 경우,
서버가 100,200,300 바이트의 경계를 구분하지 못하고 350, 250 바이트 데이터를 읽을 수 있다.
따라서  TCP 서버/클라이언트를 작성할 때는 데이터 경계 구분을 위한 상호 약속이 필요하며,
이를 애플리케이션 수준에서 처리해야만 한다.


send() 함수
- 애플리케이션 데이터를 송신 버퍼에 복사함으로써 궁극적으로 하부 프로토콜(TCP/IP)에 의해 데이터가 전송되도록 한다.
send() 함수는 데이터 복사가 성공적으로 이루어지면 바로 리턴하므로, send() 함수가 성공했다고 실제 데이터 전송이
완료된 것은 아니다.

int send(
SOCKET s,
const char* buf,
int len,
int flags
);

SOCKET s,
- 통신할 대상과 연결된 소켓이다.

const char* buf,
- 보낼 데이터를 담고 있는 애플리케이션 버퍼의 주소다.

int len,
- 보낼 데이터 크기(바이트) 이다.

int flags
- send() 함수의 동작을 바꾸는 옵션이며, 보통 0을 사용한다.
- 드물게 MSG_DONTROUTE 와 MSG_OOB 을 사용하는 경우도 있다.

send() 함수는 첫번째 인자로 사용한 소켓의 특성에 따라 다음과 같이 두 종류의 성공적인 리턴을 할 수 있다.

1. 블로킹 소켓
- 지금까지 생성한 모든 소켓은 블로킹 소켓인데, 블로킹 소켓에 대해 send() 함수를 호출할 때,
송신 버퍼의 여유 공간이 send() 함수의 세 번째 인자인 len 보다 작을 경우 해당 프로세스는 대기 상태가 된다.
송신 버퍼에 충분한 공간이 생기면 프로세스는 깨어나고, len 크기만큼 데이터 복사가 이루어진 후 send() 함수가 리턴한다.
이 경우 send() 함수의 리턴 값은 len과 같게 된다.

2. 넌블로킹 소켓
- ioctlsocket() 함수를 이용하면 블로킹 소켓을 넌블로킹 소켓으로 바꿀 수 있다.
넌블로킹소켓에 대해 send() 함수를 호출하면, 송신 버퍼의 여유 공간만큼 데이터를 복사한 후 실제 복사한 데이터 바이트
수를 리턴한다. 이 경우 send() 함수의 리턴값은 최소 1, 최대 len이 된다.








recv() 함수
- 수신 버퍼에 도착한 데이터를 애플리케이션 버퍼로 복사하는 역활을 하는 함수다.

int recv(
SOCKET s,
char* buf,
int len,
int flags
);

SOCKET s,
- 통신할 대상과 연결된 소켓이다.

char* buf,
- 받은 데이터를 저장할 애플리케이션 버퍼의 주소다.

int len,
- 수신 버퍼로부터 복사할 최대 데이터 크기(바이트) 이다. 이 값은 buf가 가리키는 버퍼의 크기보다 크면 안된다.

int flags
- recv() 함수의 동작을 바꾸는 옵션이며, 보통 0을 사용한다.
- 드물게 MSG_PEEK와 MSG_OOB 를 사용하는 경우가 있다.
- recv() 함수는 수신 버퍼의 데이터를 애플리케이션 버퍼로 복사한 후 해당 데이터를 수신 버퍼에서 삭제한다.
- 그러나 MSG_PEEK 옵션을 사용하면 수신 버퍼에 데이터가 계속 남아 있게 된다.

recv() 함수는 두 종류의 성공적인 리턴을 할 수 있다.
1. 수신 버퍼에 데이터가 도달한 경우
- recv() 함수의 세 번째 인자인 len보다 크지 않은 범위 내에서 가능한 많은 데이터를 애플리케이션 버퍼로 복사한다.
- 이 경우 복사한 바이트 수가 리턴되며, 가능한 최대 리턴값은 len 이 된다.

2. 접속이 정상 종료된 경우
- 상대 애플리케이션이 closesocket() 함수를 사용하여 접속을 종료하면, TCP 프로토콜 수준에서 접속 종료를 위한
패킷 교환 절차가 일어난다. 이 경우 recv() 함수는 0을 리턴한다.
recv() 함수의 리턴값이 0인 경우를 정상 종료라 부른다. (normal close = graceful close) [각주:1]


recv() 함수 사용시 주의할 점은,
세 번째 인자인 len 으로 지정한 크기보다 작은 데이터가 애플리케이션 버퍼로 복사될 수 있다는 사실이다.
이는 TCP 가 메시지 경계를 구분하지 않는다는 특성에 기인한 것이며, 자신이 받을 데이터의 크기를 미리 알고 있다면, 이 크기만큼 받을때까지 recv() 함수를 여러번 호출해야 한다. 예제에서는 사용자 정의 함수인 recvn() 을 정의해서 처리하고 있다.


사용예)

//사용자 정의 데이터 수신 함수
int recvn(SOCKET s, char *buf, int len, int flags)[각주:2]
{
 int received;[각주:3]
 char *ptr = buf;[각주:4]
 int left = len;[각주:5]
 while( left > 0 )[각주:6]
 {
  received = recv(s,ptr,left,flags);[각주:7]
  if(received == SOCKET_ERROR)
  return SOCKET_ERROR;
  else if(received == 0)[각주:8]
  break;[각주:9]
  left -= received;[각주:10]
  ptr += received;[각주:11]
  
 }
 return (len - left);[각주:12]
}















  1. TCP 종료시에 FIN,ACK,FIN,ACK 네 개의 패킷 교환이 일어난다.그러나 때로는 FIN, FIN/ACK, ACK 세 개의 패킷이 교환되기도 한다.먼저 closesocket() 함수를 호출한 소켓의 TCP 포트는 FIN_WAIT 상태를 거친 후 사라진다.보통 FIN_WAIT 상태에 머무르는 시간은 TCP/IP 구현마다 다르지만 일반적으로 5분을 넘지 않는다. [본문으로]
  2. recv() 함수와 동일한 인자를 사용한다. [본문으로]
  3. recv() 함수의 리턴값을 저장하는 변수다. [본문으로]
  4. 포인터 변수 ptr이 애플리케이션 버퍼의 시작 주소를 가리키도록 한다. 데이터를 읽을 때마다 ptr 변수는 증가한다. [본문으로]
  5. left 변수는 아직 읽지 않은 데이터 크기를 나타낸다. [본문으로]
  6. 읽지 않은 데이터가 존재시 계속 루프를 돈다. [본문으로]
  7. recv() 함수를 호출하고, 오류가 발생시 리턴한다. [본문으로]
  8. 함수 리턴값이 0이면 정상종료, 상대가 데이터를 더 보내지 않을 것이므로 루프를 빠져나간다. [본문으로]
  9. 함수 리턴값이 0이면 정상종료, 상대가 데이터를 더 보내지 않을 것이므로 루프를 빠져나간다. [본문으로]
  10. 각각 변수를 갱신한다. [본문으로]
  11. 읽은 바이트 수를 리턴한다.정상 종료를 제외하면 left 변수는항상 0이므로 리턴값은 len이 된다. [본문으로]
  12. 각각 변수를 갱신한다. [본문으로]

'Windows > Network Programming' 카테고리의 다른 글

send(), recv() 사용 분석  (0) 2011.07.16
TCP Client 분석  (0) 2011.07.15
TCP Server 분석  (0) 2011.07.15
TCP Server / Client  (0) 2011.07.15

일반적으로 TCP 클라이언트는 다음의 순서를 가진다.

1. socket()
2. connect()
3. send(), recv() 등 통신을 수행
4. closesocket() 를 이용해 소켓을 닫는다.

connect() 함수
- 클라이언트가 서버에 접속하여 TCP 프로토콜 수준의 연결이 이루어지도록 한다.

int connect(
SOCKET s,
const struct sockaddr* name,
int namelen
);

SOCKET s,
- 서버와 통신을 위해 만든 소켓

const struct sockaddr* name,
- 소켓 주소 구조체 변수를 서버 주소(원격 IP , 원격 포트번호) 로 초기화한 후 ,이 변수의 주소값을 여기에 대입한다.

int namelen
- 소켓 주소 구조체 변수의 길이(바이트) 를 대입한다.

클라이언트는 서버와 달리 bind() 함수를 호출하지 않으며, 그 상태에서 connect() 함수를 호출하면 운영체제는 자동으로
지역 IP 주소와 지역 포트 번호를 설정한다. 이때 자동으로 할당되는 포트 번호는 운영체제에 따라 다를 수 있으며,
윈도우일 경우 1024~5000 중 하나가 할당된다.


사용예)
 //connect()
 SOCKADDR_IN serveraddr;[각주:1]
 serveraddr.sin_family = AF_INET;[각주:2]
 serveraddr.sin_port = htons(9000);[각주:3]
 serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");[각주:4]
 retval = connect(sock, (SOCKADDR *) &serveraddr, sizeof(serveraddr));
 if(retval == SOCKET_ERROR ) err_quit("connect()");










  1. 소켓 주소 구조체 변수를 초기화한다. [본문으로]
  2. 소켓 주소 구조체 변수를 초기화한다. [본문으로]
  3. 소켓 주소 구조체 변수를 초기화한다. [본문으로]
  4. 원격 IP주소나 루프백 주소를 대입하면 된다. [본문으로]

'Windows > Network Programming' 카테고리의 다른 글

send(), recv() 사용 분석  (0) 2011.07.16
데이터 전송 함수 및 소켓 데이터 구조체  (0) 2011.07.16
TCP Server 분석  (0) 2011.07.15
TCP Server / Client  (0) 2011.07.15

서버쪽 함수

1. socket() 함수를 이용해 생성
2. bind() 함수를 이용해 지역IP 와 지역 포트 번호 결정
3. listen() 함수를 이용해 TCP상태를 LISTENING 상태로 변경
4. accpet() 함수를 이용해 접속한 클라이언트와 통신할 수 있는 새로운 소켓을 생성. 이때 원격IP주소와 포트번호 결정됨
5. send(), recv() 등의 함수를 이용해 통신을 수행,
6. closesocket() 함수를 이용해 소켓을 종료한다.

새로운 클라이언트가 접속시 4~6의 과정을 반복한다.

1. bind()
int bind(
SOCKET s,
const struct sockaddr* name,
int namelen
);

SOCKET s,
- 클라이언트 접속을 수용할 목적으로 만든 소켓이며, 지역 IP주소와 포트번호가 아직 결정되지 않는다.

const struct sockaddr* name,
- 소켓 주소 구조체(TCP일 경우 SOCKADDR_IN 타입) 변수를 지역 IP주소와 지역 포트 번호로 초기화 후,
이 변수의 주소값을 여기에 대입한다.

int namelen
- 소켓 주소 구조체 변수의 길이(바이트) 를 대입한다.

예문)

SOCKADDR_IN serveraddr;
 ZeroMemory(&serveraddr, sizeof(serveraddr));
 serveraddr.sin_family = AF_INET;
 serveraddr.sin_port = htons(9000);
 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 retval = bind(listen_sock, (SOCKADDR *) &serveraddr, sizeof(serveraddr));
 if(retval == SOCKET_ERROR ) err_quit("bind()");

// 소켓 주소 구조체 변수를 선언후에 0으로 초기화한다. ZeroMemory() (API 함수) 또는 memset()을 이용한다.
// 인터넷 주소 체계를 사용한다는 의미로 AF_INET을 대입한다.
// 포트 번호를 9000번으로 설정하며, htons() 함수로 바이트 정렬을 변경한 값을 대입한다.
// 서버의 지역 IP 주소를 설정한다. 서버의 경우 특정 IP 주소보다는 INADDR_ANY 값을 사용하는 것이 바람직하다.
// 서버가 2개 이상일 경우 INADDR_ANY 값을 지역 주소로 설정하면 클라이언트가 어느 주소로 접속하든 처리 가능하다.
// bind() 함수를 호출하고, 두번째 인자는 항상 (SOCKADDR*) 타입으로 반환해야 한다.



2. listen() 함수
int listen(
SOCKET s,
int backlog
);

SOCKET s,
- 클라이언트 접속을 수용할 목적으로 만든 소켓으로, bind() 함수에 의해 지역 IP 주소와 지역 포트 번호가 설정된 상태이다.

int backlog
- 서버가 당장 처리하지 않더라도 접속 가능한 클라이언트의 수다. 클라이언트의 접속 정보는 연결 큐에 저장되며,
backlog 는 이 연결 큐의 길이를 나타낸다고 보면 된다. 하부 프로토콜에서 지원 가능한 최대값을 사용시 SOMAXCONN 대입.


3. accept() 함수
- 서버에 접속한 클라이언트와 통신할 수 있도록 새로운 소켓을 생성 후, 리턴하는 역활을 한다.
또한 접속한 클라이언트의 IP 주소와 포트 번호를 알려준다. 클라이언트 입장에서는 지역 IP 주소와 포트번호.
SOCKET accept(
SOCKET s,
struct sockaddr* addr,
int* addrlen
);

SOCKET s,
- 클라이언트 접속을 수용할 목적의 소켓

struct sockaddr* addr,
- 소켓 주소 구조체 변수를 정의한 후, 이 변수의 주소값을 여기에 대입한다.
- accpet() 함수는 addr이 가리키는 메모리 영역을 클라이언트의 IP 주소와 포트 번호로 채워 넣는다.

int* addrlen
- 정수형 변수를 addr이 가리키는 메모리 영역의 크기로 초기화한 후, 이 변수의 주소값을 여기에 대입한다.
accept() 함수가 리턴하면 정수형 변수는 addrlen은 함수가 초기화한 메모리 크기값(바이트) 을 가진다.

// 클라이언트의 IP 주소와 포트 번호를 알 필요가 없다면 addr과 addrlen에 NULL을 사용하면 된다.


사용예)

//데이터 통신에 사용할 변수
 SOCKET client_sock;[각주:1]
 SOCKADDR_IN clientaddr;[각주:2]
 int addrlen;[각주:3]
 char buf[BUFSIZE+1];
 
 while(1)[각주:4]
 {
  //accept
  addrlen = sizeof(clientaddr);[각주:5]
  client_sock = accept(listen_sock, (SOCKADDR*) &clientaddr , &addrlen);[각주:6]
  if(client_sock == INVALID_SOCKET )
  {
   err_display("accpet()");
   continue;
  }
  printf("\n[TCP 서버] 클라이언트 접속 : IP 주소 : %s, 포트번호 : %d\n",
    inet_ntoa(clientaddr.sin_addr),
    ntohs(clientaddr.sin_port ));
    


 while(1)
 {
//클라와 데이터 통신[footnote][/footnote]
 }
 
closesocket(client_sock);
printf("\n[TCP Server] 클라이언트 종료 : IP 주소 : %s , 포트번호 : %d\n",
   inet_ntoa(clientaddr.sin_addr),
   ntohs(clientaddr.sin_port ));
}




  1. accept() 함수의 리턴값을 저장할 SOCKET 타입 변수다. [본문으로]
  2. accpet() 함수의 두 번째 인자로 사용되며 accept() 함수 리턴 후 클라이언트의 IP 주소와 포트 번호가 여기에 저장된다. [본문으로]
  3. accept() 함수의 세번째 인자로 사용된다. [본문으로]
  4. 일반적으로 서버는 계속클라이언트 요청을 처리해야 하므로 무한 루프를 돈다. [본문으로]
  5. accept() 함수를 호출하기 전에, 세 번째 인자로 사용할 정수형 변수 addrlen을 소켓 주소 구조체 변수(clientaddr)의 크기로 초기화한다. [본문으로]
  6. accept() 함수를 호출하고 오류 처리를 한다. 이전에 사용한 소켓 함수와 달리 오류가 발생시 err_display() 함수를 이용해 화면에 표시한 후, 다시 돌아간다. 심각한 오류가 아니면 이와 같이 서버를 계속 구동하는 것이 바람직하다. [본문으로]

'Windows > Network Programming' 카테고리의 다른 글

send(), recv() 사용 분석  (0) 2011.07.16
데이터 전송 함수 및 소켓 데이터 구조체  (0) 2011.07.16
TCP Client 분석  (0) 2011.07.15
TCP Server / Client  (0) 2011.07.15

1.  Client Source


#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>

#define BUFSIZE 512

//소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER |
   FORMAT_MESSAGE_FROM_SYSTEM ,
   NULL,
   WSAGetLastError(),
   MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
   (LPTSTR)&lpMsgBuf,0,NULL);
 MessageBox(NULL,(LPTSTR)lpMsgBuf,msg,MB_ICONERROR);
 LocalFree(lpMsgBuf);
 exit(-1);
  
}

//소켓 함수 오류 출력

void err_display(char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER |
   FORMAT_MESSAGE_FROM_SYSTEM,
   NULL,WSAGetLastError(),
   MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
   (LPTSTR)&lpMsgBuf, 0, NULL);
 printf("[%s] %s",msg,(LPCTSTR)lpMsgBuf);
 LocalFree(lpMsgBuf);
  
}

//사용자 정의 데이터 수신 함수
int recvn(SOCKET s, char *buf, int len, int flags)
{
 int received;
 char *ptr = buf;
 int left = len;

 while( left > 0 )
 {
  received = recv(s,ptr,left,flags);
  if(received == SOCKET_ERROR)
  return SOCKET_ERROR;
  else if(received == 0)
  break;
  left -= received;
  ptr += received;
  
 }
 return (len - left);
}

 

 


int main(int argc, char* argv[])
{
 int retval;

 //윈속 초기화
 WSADATA wsa;
 if(WSAStartup(MAKEWORD(2,2) , &wsa) != 0)
  return -1; // 0이 아닐 시 -1리턴
 
 //socket()
 SOCKET sock =socket(AF_INET,SOCK_STREAM,0);
 if(sock == INVALID_SOCKET) err_quit("socket()");
 
 //connect()
 SOCKADDR_IN serveraddr;
 serveraddr.sin_family = AF_INET;
 serveraddr.sin_port = htons(9000);
 serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 retval = connect(sock, (SOCKADDR *) &serveraddr, sizeof(serveraddr));
 if(retval == SOCKET_ERROR ) err_quit("connect()");


 //데이터 통신에 사용할 변수
 int len;
 char buf[BUFSIZE+1];
 
 while(1)
 {
  //데이터 입력
  ZeroMemory(buf, sizeof(buf));
  printf("\n[보낼 데이터]");
  if(fgets(buf, BUFSIZE+1, stdin) == NULL)
   break;
  //\n 문자 제거
  len = strlen(buf);
  
  if(buf[len-1] =='\n')
   buf[len-1] = '\0';
  if(strlen(buf) == 0)
   break;

  //데이터 보내기
  retval = send(sock,buf,strlen(buf), 0);
  if(retval == SOCKET_ERROR)
  {
   err_display("send()");
   break;
  }

  printf("[TCP 클라이언트] %d 바이트를 보냈습니다! \n", retval);
  
  //데이터 받기
  retval = recvn(sock,buf,retval,0);
  if(retval == SOCKET_ERROR)
  {
  err_display("recv()");
  break;
  }
  else if(retval==0)
  break;

  //받은 데이터 출력
  buf[retval] = '\0';
  printf("[TCP 클라이언트] %d 바이트를 받았습니당! \n" , retval);
  printf("[받은 데이터] %s\n", buf);

 }

 //closesocket()

 closesocket(sock);

 


 //윈속 종료
 WSACleanup();
 return 0;


}





2. Server Source


#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>

#define BUFSIZE 512

//소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER |
   FORMAT_MESSAGE_FROM_SYSTEM ,
   NULL,
   WSAGetLastError(),
   MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
   (LPTSTR)&lpMsgBuf,0,NULL);
 MessageBox(NULL,(LPTSTR)lpMsgBuf,msg,MB_ICONERROR);
 LocalFree(lpMsgBuf);
 exit(-1);
  
}

//소켓 함수 오류 출력

void err_display(char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER |
   FORMAT_MESSAGE_FROM_SYSTEM,
   NULL,WSAGetLastError(),
   MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
   (LPTSTR)&lpMsgBuf, 0, NULL);
 printf("[%s] %s",msg,(LPCTSTR)lpMsgBuf);
 LocalFree(lpMsgBuf);
  
}

int main(int argc, char* argv[])
{
 int retval;

 //윈속 초기화
 WSADATA wsa;
 if(WSAStartup(MAKEWORD(2,2) , &wsa) != 0)
  return -1; // 0이 아닐 시 -1리턴
 
 //socket()
 SOCKET listen_sock =socket(AF_INET,SOCK_STREAM,0);
 if(listen_sock == INVALID_SOCKET) err_quit("socket()");
 
 //bind()
 SOCKADDR_IN serveraddr;
 ZeroMemory(&serveraddr, sizeof(serveraddr));
 serveraddr.sin_family = AF_INET;
 serveraddr.sin_port = htons(9000);
 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 retval = bind(listen_sock, (SOCKADDR *) &serveraddr, sizeof(serveraddr));
 if(retval == SOCKET_ERROR ) err_quit("bind()");
 
 //listen
 retval = listen(listen_sock, SOMAXCONN);
 if(retval == SOCKET_ERROR ) err_quit("listen()");

 //데이터 통신에 사용할 변수
 SOCKET client_sock;
 SOCKADDR_IN clientaddr;
 int addrlen;
 char buf[BUFSIZE+1];
 
 while(1)
 {
  //accept
  addrlen = sizeof(clientaddr);
  client_sock = accept(listen_sock, (SOCKADDR*) &clientaddr , &addrlen);
  if(client_sock == INVALID_SOCKET )
  {
   err_display("accpet()");
   continue;
  }
  printf("\n[TCP 서버] 클라이언트 접속 : IP 주소 : %s, 포트번호 : %d\n",
    inet_ntoa(clientaddr.sin_addr),
    ntohs(clientaddr.sin_port ));
    
 

 //클라와 데이터 통신
 while(1)
 {
 
 
 retval = recv(client_sock,buf,BUFSIZE,0);
 if(retval == SOCKET_ERROR)
 {
  err_display("recv()");
  break; 
 }

 else if(retval == 0)
 {
  break;
 }
 //받은 데이터 출력
 buf[retval] = '\0';
 printf("[TCP/%s:%d] %s\n",
  inet_ntoa(clientaddr.sin_addr),
  ntohs(clientaddr.sin_port ), buf);
 

 //데이터 보내기
 retval = send(client_sock,buf,retval,0);
 if(retval == SOCKET_ERROR)
 {
  err_display("send()");
  break;
 }
 }

 //closesocket()

 closesocket(client_sock);
 printf("\n[TCP Server] 클라이언트 종료 : IP 주소 : %s , 포트번호 : %d\n",
   inet_ntoa(clientaddr.sin_addr),
   ntohs(clientaddr.sin_port ));
}
 //closesocket()
 closesocket(listen_sock);

 //윈속 종료
 WSACleanup();
 return 0;


}


'Windows > Network Programming' 카테고리의 다른 글

send(), recv() 사용 분석  (0) 2011.07.16
데이터 전송 함수 및 소켓 데이터 구조체  (0) 2011.07.16
TCP Client 분석  (0) 2011.07.15
TCP Server 분석  (0) 2011.07.15

 



 



CBR600RR..

내가 가장 사랑하는 모델이고 가장 사고 싶은 기종이다.

혼다의 내구성과 성능은 이미 말하지 않아도 누구나 다 알

정도로 이 차 또한 혼다의 장점을 갖추고 있는 차량이다.

천만원이 넘어가지만, 그래도 너무 갖구싶다..ㅠ.ㅠ

알차를 타보지 않은사람은 왜 위험하게 바이크를 타냐고 하지만

그건 잘 몰라서 하는 애기이다..

알차의 매력은 차와는 비교할 수가 없다.

차와는 비교할 수 없는 엄청난 가속력과 최고속, 코너링, 투어링..

물론 개인취향이고,, 또한 사고의 위험성이 높은것두 인정하지만..

한번 맛을 알게되면 헤어나올 수 없을 것이다.

'Review > Moto Bike Review' 카테고리의 다른 글

ZXR 400RR  (0) 2011.08.12

+ Recent posts