태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

eternally full with hope...

블로그 이미지
영원히 희망으로 가득하길...
by eternalbleu
  • 464617Total hit
  • 100Today hit
  • 316Yesterday hit

'리눅스'에 해당되는 글 5건

  1. 2006/12/22
    rTorrent 사용법
  2. 2006/07/09
    우분투 대퍼 사용소감!!!
  3. 2006/04/28
    유닉스 시스템 콜 처리
  4. 2006/03/27
    다중 연결 허용 서버의 구현법 (socket programming)
  5. 2006/03/23
    간만에 리눅스로 다시 복귀!!!
요즘 새롭게 떠오른 P2P 프로토콜이 있습니다.

바로 BitTorrent 라는 프로토콜로 Tracker 라는 교환서버를 기반으로 동작하는 P2P의 한 형태입니다. 자세한 사항은 위키 페디아를 참조하세요. 장점이자 단점은 검색이라는 것이 아닌 .torrent 파일을 가지고 교환된다는 점이죠. (대신에 .torrent 를 다루는 폐쇄형 공유 커뮤니티들이 더러 있습니다)

사용자 삽입 이미지

http://en.wikipedia.org/wiki/BitTorrent


사용자 삽입 이미지

이 게임은 클라이언트는 용량만 3GB이다

덕분에 torrent 파일이 없으면 다운로드는 요원한 일이라는 것은 장점이라면 장점. 단점이라면 단점이라면 단점입니다. 하지만 대용량 파일을 가진 컨텐츠를 배포해야하는 서비스에서는 이 만큼 좋은 배포 형태도 없죠.

가깝게는 블리자드사의 World Of Warcraft 한글판을 이 형태로 배포하고 있습니다. 서비스 제공자의 입장에서는 최소한의 비용 투자로 최대의 효과를 거두어 들이는 거죠 ^^

당연하겠지만 역시 리눅스 콘솔에도 이 프로토콜의 콘솔 클라이언트가 있습니다. rTorrent 라는 녀석입니다. ncurse 라이브러리를 이용해서 콘솔 프로그램임에도 불구하고 굉장히 편하게 사용할 수 있다는 장점이 있습니다.
(오페라 브라우저의 다운로드 매니저는 기본적으로 .torrent 를 지원합니다.)

이번에는 rTorrent 라는 프로그램을 사용해보려고 합니다.

우선은 aptitude 를 이용해서 rTorrent를 설치합니다.
사용자 삽입 이미지

aptitude install rtorrent

사용자 삽입 이미지

엔터키를 이용해 load> 라는 창에 .torrent 의 내용을 입력한다. (파일, URL 무관하다)

방향키로 다운로드 리스트 아이템을 선택하고 오른쪽 버튼을 누르면 해당 다운로드에 대한 정보를 볼 수 있다.
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지

※ rTorrent 개발 페이지에서 가져온 단축키 내역입니다. 최신 버전과 약간 차이가 있는 듯합니다.

torrents 추가 및 제거
backspace URL, 파일 이름을 이용해서 torrent 를 추가한다. 디렉토리 내용을 보고 자동 완성하려고 Tab 키를 이용할 수 있다. 이때 ~/torrent/* 같이 와일드 카드 문자를 사용해서 입력하는 것이 가능하다.
return torrent 를 비 활성화된 상태로 남긴다는 점을 제외하면 backsapce 와 동일한 기능을한다. (활성화 단축키 ^s )
^O 선택된 torrent 를 위한 새로운 다운로드 디렉토리를 설정한다. torrent 가 아직 활성화된 상태가 아닐때만 동작한다.
^s 다운로드 시작. (완료 직전 이라면 해싱 작업을 먼저 시작한다)
^d 다운로드 중지. 혹은 정지된 다운로드를 제고
^r 다운로드와 무관하게 torrent 의 해싱 체크를 시작한다.

대역폭 제한
a/s/d 1/5/50 KB 씩 업로드 대역폭 증가.
z/x/c 1/5/50 KB 씩 업로드 대역폭 감소.
A/S/D 1/5/50 KB 씩 다운로드 대역폭 증가.
Z/X/C 1/5/50 KB 씩 다운로드 대역폭 감소.
※ 대역폭 제한은 단일 torrent 에 대한 제한이 아니라 전역적으로 제한된다.

네비게이션
1. 전역키
^q 프로그램 종료. (중복으로 명령을 내리면 트래커와 주고받는 신호를 무시하고 종료한다.)
up/down torrent 선택
left 이전 화면으로 복귀

2. 메인 뷰
right 다운로드 뷰로 전환
^r 토런트의 해시 체크 시작
+/- 토런트의 우선 순위 변경
l 로그 보기. Space 키로 종료
M-1 모든 다운로드 내역 보기
M-2 이름 순으로 모든 다운로드 내역 보기
M-3 시작된 다운로드 내역 보기
M-4 정지된 다운로드 내역 보기
M-5 완료된 다운로드 내역 보기
M-6 해싱중인 다운로드 내역 보기

3. 다운로드 뷰 키보기
right 토런트 파일 리스트로 전환
left 메인 뷰로 전환
1/2 최대 업로드 조절
3/4 최소 피어수 조절
5/6 최대 피어수 조절
o 트리커 리스트 출력.스페이스바로 한 구룹내의 트래커들을 순환. * 키를 이용해 선택된 트래커 의 활성화 설정을 토글
p 피어와 토런트 정보를 보기
t/T 트래커 요청 시작. 대문자 T를 이용하면 최소 요청 간격을 무시하고 강제로 요청을 할 수 있음.
u 전송 내역 보기
i Chunk 빈도 보기

4. 파일리스트 뷰
left 다운로드 뷰로 전환
space 파일 우선 순위 변경
* 모든 파일의 우선 순위 변경

TRACKBACK 0 AND COMMENT 0
오늘 우분투 대퍼를 설치했습니다.

워낙에 소문이 자자했지만 뭐 그러려니하다가 간만에 리눅스를 다시 설치해봅니다. (한 일년만인가 ㅡㅡ;;) 윈도우가 2번째 하드에 설치되있어서 GRUB 설정이 바로 안되더군요. -_- 귀찮게 스리...

정말로 많이 좋아졌더군요. 좋아졌다는 것은 시스템적인 측면이 아니라.. 최초 사용자의 접근성 측면에서 대폭 향상이 이루어진 듯합니다. 내공 높으신 분들은 그때나 지금이나 잘들 이용하시 겠지만 저 같은 하수인 경우에는 정말 엄청나게 힘들었던 설정들이 이제는 그냥 되네요. 헐;;;

대표적인게 바로 윈도우 글꼴... 예전에는 볼드체가 않나와서 pango 패치까지 해가면서 설정했던 것 같은데 이제는 fc-cache 만하면 바로 넘어가네요 -_-;;;

무엇보다도 SCIM 이란 놈이 생겼네요. 아마 입력기의 통합형 인터페이스 비슷한놈이라고 생각되는데 맞는지 모르겠습니다. (윈도우의 IME 처럼...)



단지 이제 아쉬운건 오픈 오피스네요. -_-; PPT의 문서 인식률은 거의 100%더군요. 단지 속도가 MS의 그것보다 반응이 상당히 느리고 애니메이션에 대한 인식이 불완전한 것 같습니다. (얼추보아서....) 아마 오픈 오피스 전용 포맷을 이용하면 해결이 되겠지만...

ODF 를 MS에서도 공식적으로 지원한다고 발표했던데... 나중에 오픈 오피스와 MS 오피스 사이에 이런식의 문제가 발생하는게 아닐까 불안하네요.

WORD 파일은 예전에 해봤을때 거의 인식이 잘 안되던데-_-; 지금은 어떤지 모르겠습니다.
(요즘은 워드보다 PPT 사용률이 높아서;;)
TRACKBACK 0 AND COMMENT 0

2.5 소켓 관련 UNIX 시스템 콜

2.5.1 signal()

▶ 유닉스 시스템에서 어떤 이벤트(event)가 발생하면 이것을 프로세스 사이에

알리는 수단으로 시그널이 사용된다.

표 2-3 소켓 관련 시그널 종류

SIGINT

인트럽트 키(Ctrl+C) 입력시 발생

SIGFPE

부동 소수점 연산 에러를 나타냄

SIGIO

I/O가 가능한 상태를 나타냄.

SIGURG

Out-of-band 데이터 도착과 같은 긴급한(urgent) 소켓 상태를 나타냄.

▶ 시그널이 발생하였을 때 유닉스 커널이 제공하는 디폴트 처리 내용 대신 다른

동작을 수행하도록 하려면 signal() 시스템 콜을 사용한다. 아래에서 signal

(SIGIO, sigio_func) 호출 후 SIGIO 시그널이 발생하면 sigio_func() 함수가 수행

된다.

      #include <signal.h>
      int sigio_func();               /* 사용자 정의 함수 선언 */
      main() {
      signal(SIGIO, sigio_func); /* 시그널 처리 함수 지정 */
      :
      }

        int sigio_func() {
        /* SIGIO 시그널 발생시 처리 내용 */
        }

▶ 어떤 시그널이 발생하였을 때 이를 단순히 무시하려면 다음과 같이 무시할 시

그널의 종류(예를 들면 SIGIO)를 지정하고 옵션으로 시그널 무시(SIG_IGN)를 선

택한다.

      signal(SIGIO, SIG_IGN);

■ signal_test.c

      카운터 프로그램이 실행되는 도중에 사용자가 Ctrl-C를 입력하면 시그널 SIGINT

      가 발생하는데, 이 때 프로그램이 종료되는 것이 아니라 my_signal()이라는 함수가

      호출된다.

      실행예

        > signal_test
        0
        1
        ^C
        Ctrl-C pressed.
        2
        3
        ^C
        Ctrl-C pressed.
        4
        ^C
        Ctrl-C pressed.
        >

      프로그램 리스트

      /*---------------------------------------
      파일명 : signal_test.c
      기 능 : signal() 시스템 콜 사용 예
      컴파일 : cc -o signal_test signal_test.c
      사용법 : signal_test
      ----------------------------------------*/
      #include <sys/types.h>
      #include <signal.h>
      #include <stdio.h>
      #include <unistd.h>
      int my_signal();    /* 새로운 시그널 처리 함수 선언 */
      int count = 0;       /* Ctrl-C 입력 횟수 카운터 */

      int main() {
      int i = 0;
      if(signal(SIGINT, my_signal) == SIG_ERR) {

      printf("singal() error\n");
      exit(0);
      }
      while(count < 3) {
      sleep(1);      /* 1초간 기다림 */
      printf("%d\n", i++);
      }
      }
      /* end of main  */

      /* 시그널 처리 함수 정의 */
      int my_signal() {
      printf("\nCtrl-C pressed.\n");
      count++;

      signal(SIGINT, my_signal);  /* signal()을 다시 호출함 */

      return 0;
      }

2.5.2 fork()

유닉스에서 프로세스는 fork()를 이용해서 자신과 똑같은 기능을 수행

하는 프로세스를 하나 복제할 수 있다.

두 프로세스는 프로그램 코드, 스택, 파일기술자, 소켓번호 등은 공유하나, 변

수들은 공유하지 않는다.

▶ fork()가 불리면 그 순간에 하나의 프로세스가 두 개의 프로세스로 되는데, 두

프로세스는 수행할 일을 구분하기 위하여 두 프로세스의 fork() 리턴문이 서로 다

르다는 것을 이용한다.

▶ 새로 생긴 자식 프로세스의 ID 번호(PID: Process Identification)는 부모 프로

세스의 PID와 구별된다.

▶ 부모 프로세스에게는 fork()의 리턴값으로 새로 생성된 자식 프로세스

의 PID가 리턴되며 자식 프로세스의 fork()의 리턴값은 0이 된다.

그림 2-14 fork()의 수행과정

▶ 프로세스의 작업 구분 예

        int  PID;
        PID = fork();
        if(PID == 0) {

        child_work(); /* 자식 프로세스용 코드 */
        } else {
        parent_work();/* 부모 프로세스용 코드 */
        }

■ fork_test.c

      부모와 자식 프로세스가 같은 이름의 변수를 각각 증가시키고 그 결과를 확인한

      다.

프로그램 리스트

/* ----------------------------------------------------
파일명 : fork_test.c
기 능 : fork() 시스템 콜 사용 예
컴파일 : cc -o fork_test fork_test.c
사용법 : fork_test
-----------------------------------------------------*/
#include <sys/types.h>
#include <unistd.h>
int global_var = 0;      /* 전역 변수 선언 */

int main(void) {
pid_t pid;
int    local_var = 0;     /* 지역 변수 선언 */
if((pid = fork()) < 0) {
printf("fork error\n");
exit(0);

/* 자식 프로세스 */
} else if (pid == 0) {
global_var++;
local_var++;
printf("CHILD - my pid is %d and parent's pid is %d\n", getpid(), getppid());
} else {

/* 부모 프로세스 */
sleep(2);/* 2초 쉰다 */
global_var += 5;
local_var += 5;
printf("PARENT - my pid is %d, child's pid is %d\n", getpid(), pid);
}
printf("\t global var : %d\n", global_var);
printf("\t local var : %d\n", local_var);
}

    실행예
    > fork_test
    CHILD - my pid is 12557 and parent's pid is 12556
    global var : 1
    local var : 1
    PARENT - my pid is 12556 and child's pid is 12557
    global var : 5
    local var : 5

    ▶ 여기서 부모 프로세스가 global_var과 local_var을 각각 5씩 증가시켰

    는데 6이 되지 않고 5가 되었다는 사실에 주목하자!! (파일이나 소켓은 공

    유하지만 변수는 공유하지 않는다)

    참조) http://cafe.naver.com/segame.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=94

TRACKBACK 0 AND COMMENT 0

다중 사용자의 connect 를 처리하기 위한 방법은 총 3가지의 방식으로 구분한다.

1. 유닉스 호환환경에서 제공하는 fork() 를 이용한 다중 프로세스
2. IO 멀티플렉싱을 이용한 다중 연결
3. 멀티 쓰레드를 이용한 다중 연결

3가지의 방법은 어떤 것이 좋다 나쁘다고 할 것이 아니고 적당한 상황하에서 적정한 기술을 이용하는 것이 관건이라고 할 수 있을 것이다.

1. fork() 이용 소스
[CODE] /** 멀티 프로세스를 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #define BUFFSIZE 30 void error_handling(const char* message); void z_handler(int sig); int main(int argc, char **argv) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; struct sigaction act; int addr_size, str_len, state; pid_t pid; char message[BUFFSIZE]; if(argc!=2) { printf("USAGE: %s <port>\n", argv[0]); exit(1); } act.sa_handler = z_handler; sigemptyset(&act.sa_mask); act.sa_flags=0; state = sigaction(SIGCHLD, &act, 0); if (state != 0) { puts("sigaction() error!"); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); while(1) { addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &addr_size); if (clnt_sock == -1) continue; if ((pid ==fork()) == -1) {   close(clnt_sock);   continue; } else if (pid >0) {   puts("connection success");   close("clnt_sock");   continue; } else {   close(serv_sock);   while( (str_len = read(clnt_sock, message, BUFFSIZE)) != 0) {   write(clnt_sock, message, str_len);   write(1, message, str_len);   }   puts("connection closing");   close(clnt_sock);   exit(0); } } return 0; } void z_handler(int sig) { pid_t pid; int rtn; pid = waitpid(-1, &rtn, WNOHANG); printf("zombi process ID: %d\n", pid); printf("return data : %d\n", WEXITSTATUS(rtn)); } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]

2. select 이용 소스
[CODE] /** IO 멀티플렉싱을 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #define BUFFSIZE 100 void error_handling(const char* message); int main(int argc, char **argv) { int serv_sock; struct sockaddr_in serv_addr; fd_set reads, temps; int fd_max; char message[BUFFSIZE]; int str_len; struct timeval timeout; if (argc != 2) { printf("USAGE : %s <port>\n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) error_handling("bind() error"); if (listen(serv_sock, 5) == -1) error_handling("listen() error"); FD_ZERO(&reads); FD_SET(serv_sock, &reads); fd_max = serv_sock; while (1) { int fd, str_len; int clnt_sock, clnt_len; struct sockaddr_in clnt_addr; temps = reads; timeout.tv_sec = 5; timeout.tv_usec = 0; if (select(fd_max + 1, &temps, 0, 0, &timeout) == -1)   error_handling("select() error"); for (fd = 0; fd < fd_max+1; fd++) {   if(fd == serv_sock) {   clnt_len = sizeof(clnt_addr);   clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_len);   FD_SET(clnt_sock, &reads);   if (fd_max < clnt_sock)   fd_max = clnt_sock;   printf("client connection : file descriptor %d\n", clnt_sock);   }   else {   str_len = read(fd, message, BUFFSIZE);   if (str_len == 0) {   FD_CLR(fd, &reads);   close(fd);   printf("client closing: file descriptor %d\n", fd);     }   else {   write(fd, message, str_len);   }   } } } } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]
TRACKBACK 0 AND COMMENT 0
지난 반년간은 학기중의 프로젝트 및 아르바이트가 MFC 에 종속된 것들이 많아서 리눅스를 안쓰느니만 못한 상황이었다.
그러던 것이 이번 학기에 들어오면서 완전히 역전되었다.

주요 프로젝트인 PL, 네트워크의 프로젝트가 순수 ANSI C 를 기반으로 작성하기 때문인데,...

덕분에 윈도우 플랫폼에 종속된 프로그램을 하지 않아도 되게되었다.

그래서 다시 리눅스로 복귀

이번 학기에는 리눅스에서 P2P를 이용해서 뭔가를 만들어 볼 생각이다.

나도 먼가 하나 만들어 봐야하겠다라는 생각이 들어서 랄까?
  
TRACKBACK 0 AND COMMENT 0

ARTICLE CATEGORY

분류 전체보기 (782)
Re: myself (441)
Favorite things (241)
CS&E (71)
Portfolio (22)
삼성SDS (0)

CALENDAR

«   2008/07   »
    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    

ARCHIVE