앞의 포스팅에서 설명한 멀티플렉싱 기법을 구현하는데 가장 많이 사용되는 방법이 바로 Select함수를 이용하는 것이다. 또한 리눅스 뿐만 아니라 윈도우에도 같은 이름으로 동일한 기능을 제공하는 함수가 있기 때문에 이식성에도 좋다.

 

#include<sys/select.h>

#include<sys/time.h>

 

int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptest, const struct timeval *timeout);

->성공시 0이상 실패시 -1 반환.

 

maxfd -> 검사 대상이 되는 파일 디스크립터의 수.

 

readset -> fd_set형 변수에 수신된 데이터의 존재여부에 관심 있는 파일 디스크립터 정보를 모두

  등록해서 변수의 주소값 전달.

 

writeset -> fd_set형 변수에 블로킹 없는 데이터 전송의 가능여부에 관심 있는 파일 디스크립터 정보를

  모두 등록해서 그 변수의 주소 값을 전달한다.

 

exceptset -> fd_set형 변수에 예외상황의 발생여부에 관심이 있는 파일 디스크립터 정보를 모두

     등록해서 그 변수의 주소 값 전달.

 

 

Select 함수의 기능

 

Select 함수를 이용하면 한곳에 여러개의 파일 디스크립터를 모아놓고 동시에 관찰할 수 있다.

 

1. 수신한 데이터를 지니고 있는 소켓이 존재하는지.

2. 불로킹되지 않고 데이터의 전송이 가능한 소켓은 무엇인지.

3.예외상황이 발생한 소켓은 무엇인지.

 

를 관찰할수가 있다.

 

Select 함수 호출순서 

 

 

Select 함수를 호출하기 전에는 파일디스크립터,검사 범위, 타임아웃의 설정을 해줘야 비로소 Select함수를 호출할 수가 있다.

 

파일디스크립터 설정

 

Select 함수를 이용하여 여러개의 파일디스크립터를 관리할 수 있는데, 여러개의 파일디스크립터를 모을 떄도 목적에 따라서 구분해서 모아야 하고, 파일 디스크립터를 모을 때 사용하는 것이 fd_set형 변수이다. fd_set형은 0과 1로 표현되는, 비트단위로 이뤄진 배열이다.

 

                       <fd_set 자료형>

 

fd_set형 변수를 조작하기 위해서는 매크로 함수를 이용하면 된다.

 

FD_ZERO(fd_set *fdset)        

//인자로 전달된 주소의 fd_set형 변수의 모든 비트를 0으로 초기화.

FD_SET(int fd, fd_set *fdset)

//매개변수 fdset으로 전달된 주소의 변수에 매개변수 fd로 전달된 파일 디스크립터 정보 저장.

 

FD_CLR(int fd,fd_set *fdset)

//매개변수 fdset으로 전달된 주소의 변수에 매개변수 fd로 전달된 파일 디스크립터 정보 삭제.

 

FD_ISSET(int fd,fd_set *fdset)

//매개변수 fdset으로 전달된 주소의 변수에 매개변수 fd로 전달된 파일 디스크립터 정보가 있으면 양수반환.

'Programming > Socket' 카테고리의 다른 글

I/O 멀티플렉싱  (0) 2012.05.15
로그파일을 남기는 서버  (0) 2012.05.14
클라이언트 IP 가져오기  (0) 2012.05.14
멀티프로세스 소스  (0) 2012.05.10
멀티프로세스 서버  (0) 2012.05.08

앞서 멀티프로세스 서버를 구현하였으나, 멀티프로세스 서버는 클라이언트 연결요청이 있을 때마다, 새로운 프로세스를 생성하는 기법으로, 상당히 많은 양의 연산이 요구되고, 필요한 메모리 공간도 비교적 큰 편이다.

 

따라서 프로세스의 생성을 동반하지 않고, 다수의 클라이언트들에게 서비스를 제공할 수 있는 방법으로 나온 것이 멀티 플렉싱기법이다.

 

멀티플렉싱은 물리적 장치의 효율성을 높이기 위해 최소한의 물리적인 요소만 사용해서 최대한의 데이터를 전달하기 위해 사용하는 기술이다.

 

기존의 자식프로세스를 생성해서 서비스를 하는 멀티프로세스 서버와는 달리,

 

멀티플렉싱개념을 사용하면,

 

자식프로세스가 각각의 소켓을 처리하는게 아니고, 서버하나가 각각의 소켓에 대한 서비스를 제공하는게 멀티플렉싱의 개념이다.

 

멀티플렉싱과 멀티프로세스의 차이는 서비스를 제공하는 프로세스 갯수의 차이가 각각 한개와, 클라이언트수만큼이라는 것이다.

 

 

멀티플렉싱 서버를 사용하기 적합한 경우.

1. 클라이언트와 서버간의 송수신 데이터 용량이 작은 경우 적합
2. 송수신이 연속적이지 않은 경우에 적합 
3. 멀티 프로세스 기반에 비해 많은 수의 클라이언트 처리에 적합


 

'Programming > Socket' 카테고리의 다른 글

Select 함수  (0) 2012.05.16
로그파일을 남기는 서버  (0) 2012.05.14
클라이언트 IP 가져오기  (0) 2012.05.14
멀티프로세스 소스  (0) 2012.05.10
멀티프로세스 서버  (0) 2012.05.08

 

노트에 적혀있는 글자를 보니 왠지 2칸씩 밀리는 시저사이퍼가 생각이 난다. 그래서 파이썬을 공부하고 있지만.....약간의 편법으로

 

 

ㅋ...출제자는 손으로 푼건아닌지 걱정하는데 손으로 푼건아니니까 그래도 친절하게 string.maketrans를 사용하라고 추천해준다.

maketrans를 조사해보니 테이블맵에 맞게 문자열을 변환해주는 함수라고 한다. 역시 파이썬은 없는게 없는듯...

http://taesun1114.tistory.com/entry/Python-Method 

 

사용법대로 따라서 해보자.

 

답이 나왔다. url에도 시저사이퍼를 적용해보라고 한다. map -> ocr

 

 

'Programming > Python' 카테고리의 다른 글

Python Challenge 4  (0) 2012.05.23
Python challenge 3  (1) 2012.05.23
Python challenge 2  (0) 2012.05.23
Python challenge 0  (0) 2012.05.15
Python Method  (0) 2012.05.15

 

python 스터디를 하던 도중 이 사이트를 추천해주었고, 과제로 문제푸는게 나옴.

 

첫단계를 보자마자 C와 달리 저런 숫자를 넣어도 오버플로우가 발생하지 않고 값이 잘나온다고 홍보하는것 같았지만 문제니까...

 

>>>2**38 2의 38 혹은  >>>pow(2,38)을 하면

 

간단하게 URL에 값을 넣고 다음단계로 넘어가자

 

 

'Programming > Python' 카테고리의 다른 글

Python Challenge 4  (0) 2012.05.23
Python challenge 3  (1) 2012.05.23
Python challenge 2  (0) 2012.05.23
Python challenge 1  (0) 2012.05.15
Python Method  (0) 2012.05.15

maketrans(x, [y, [z]])

This method returns a translation table that maps each character in the intab string into the character at the same position in the outtab string. Then this table is passed to the translate() function. Note that both intab and outtab must have the same length.

라고 써져있는데.. 음.. 테이블맵에 맞춰서 변환해준다는 것같다. 테이블맵을 짠후에는 translate()함수를 사용하여, 문자열을 바꿔주는 함수.

 

Maketrans(table [,deletechars])

- translate()함수에 쓰일 번역용 맵을 반환

- 인자가 하나일 경우 사전형식 입력

- 인자가 둘인경우 길이가 같은 문자열을 입력받아 x의 문자가 y로 변환

- 인자가 셋인경우 x가 y로 변환되고 z문자가 None으로 대체(삭제)

 

Help on built-in function translate:

translate(...)
    S.translate(table [,deletechars]) -> string
   
    Return a copy of the string S, where all characters occurring
    in the optional argument deletechars are removed, and the
    remaining characters have been mapped through the given
    translation table, which must be a string of length 256 or None.
    If the table argument is None, no translation is applied and
    the operation simply removes the characters in deletechars.

 

ex)

>>>a= "abcd"

>>>b=string.maketrans("abcd","efgt")

>>>c = a.translate(b)

>>>c

'efgt'

>>>

 

 

대부분의 사이트와 블로그에선 str.maketrans로 나오지만 내 우분투(11.10)파이썬(2.7.2)에서는 명령어가 먹히지 않았다. 대신 string.maketrans 를 사용해야함.

'Programming > Python' 카테고리의 다른 글

Python Challenge 4  (0) 2012.05.23
Python challenge 3  (1) 2012.05.23
Python challenge 2  (0) 2012.05.23
Python challenge 1  (0) 2012.05.15
Python challenge 0  (0) 2012.05.15

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<string.h>
#include<arpa/inet.h>
#include<stdlib.h>

 

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

        char buf[100],ip;
        int sock_serv,sock_clin,i;
        struct sockaddr_in serv_adr,clin_adr,test;
        int str_len;
        FILE *fp;
        socklen_t adr_sz;
        pid_t pid;

 

        if(argc != 2)
                printf("Please Input <Port>");

 

        sock_serv=socket(PF_INET,SOCK_STREAM,0);
        memset(&serv_adr,0,sizeof(serv_adr));
        serv_adr.sin_family=AF_INET;
        serv_adr.sin_port=htons(atoi(argv[1]));
        serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);

 

        if(bind(sock_serv,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)
                printf("bind error()");
        if(listen(sock_serv,5)==-1)
                printf("listen error()");

 

        while(1){
                adr_sz=sizeof(clin_adr);
                sock_clin=accept(sock_serv,(struct sockaddr*)&clin_adr,&adr_sz);
                memset(&test,0,sizeof(test));                
                getpeername(sock_clin,(struct sockaddr *)&test,&adr_sz);

//클라이언트의 주소정보를 getpeername함수를 이용하여 test구조체에 저장한다.


                if(sock_clin==-1){
   }
                else{
                        printf("Accept at : %s!!\n",inet_ntoa(test.sin_addr)); //클라이언트의 ip출력.
                        pid=fork();
                        if(pid==0){            //자식프로세스 영역.
                                close(sock_serv);
                                while(str_len=read(sock_clin,buf,100)!=0){
                                i=strlen(buf);
                                write(sock_clin,buf,i);
                                fp=fopen("test.txt","a");        //test.txt파일을 열고.
                                fprintf(fp,"%s\t%s",inet_ntoa(test.sin_addr),buf);  //클라이언트의 ip와 buf저장.
                                fclose(fp);
                                }
                                close(sock_clin);
                                printf("Clinet disconnected\n");
                        }
                        else
                                close(sock_clin);
                }
        }
        close(sock_serv);
        return 0;
}

 

 

test.txt를 살펴보니.

127.0.0.1과 203.x.x.x에서 접속을 했고, 입력했던 문자열이 저장되어 있다.

 

'Programming > Socket' 카테고리의 다른 글

Select 함수  (0) 2012.05.16
I/O 멀티플렉싱  (0) 2012.05.15
클라이언트 IP 가져오기  (0) 2012.05.14
멀티프로세스 소스  (0) 2012.05.10
멀티프로세스 서버  (0) 2012.05.08

서버소켓에서 나에게 접속한 클라이언트 IP를 가져오는 함수가 존재한다.

로그파일을 만들 때 사용하는 건가?

 

int Getpeername( sock, struct sockaddr* name, int *size )

sock : IP를 알고자 하는 소켓의 파일 디스크립터. 
struct sockaddr* name : 소켓 정보를 저장할 sockaddr_in구조체

int *size : 구조체 사이즈.

 

ex)

struct sockaddr_in test_adr;

 

adr_sz=sizeof(clin_adr);

getpeername(sock,(struct sockaddr*)&test_adr,&adr_sz);

 

위와 같이 선언한다면, test_adr구조체 변수안에 접속한 클라이언트의 정보가 기록된다.

하지만 위와 같이 선언하고 출력해보면.

 

우리가 알수 없는 정수형으로 값이 저장되어 있다.

 

sockaddr_in 구조체의 주소멤버의 데이터 타입은 unsigned long이다.

따라서 네트워크바이트 순서인 32비트 값을 변환시켜주어야 한다.

 

이러한 경우에 사용하는 함수가 inet_ntoa()함수이다.

 

char *inet_ntoa(struct in_addr addr)

 

성공시 변환된 해당 문자열의 포인터를 반환하고, 실패할 경우에는 -1을 반환한다.

 

 


'Programming > Socket' 카테고리의 다른 글

I/O 멀티플렉싱  (0) 2012.05.15
로그파일을 남기는 서버  (0) 2012.05.14
멀티프로세스 소스  (0) 2012.05.10
멀티프로세스 서버  (0) 2012.05.08
소켓의 옵션  (0) 2012.05.07

echo_server.c

 

 

#include<stdio.h>
#include<unistd.h>              //pid_t,socklen_t,read,write,close etc...
#include<sys/socket.h>          //socket,accept,bind,listen, etc...
#include<stdlib.h>
#include<arpa/inet.h>           //INADDR_ANY,sockaddr_in
#include<string.h>

int main(int argc,char *argv[])
{
        struct sockaddr_in serv_adr,clnt_adr;   
        int sock_ser,sock_clnt;
        char buf[100];
        pid_t pid;
        socklen_t adr_sz,len;

 

        sock_ser = socket(PF_INET,SOCK_STREAM,0);
        memset(&serv_adr,0,sizeof(serv_adr));            //소켓구조체 초기화
        serv_adr.sin_family=AF_INET;                        //서버소켓의 주소체계 결정
        serv_adr.sin_port = htons(atoi(argv[1]));        //서버포트 결정
        serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); //서버의 아이피로는 가지고 있는 아이피중 임의의 하나로 설정한다는 뜻.

 

        if(bind(sock_ser,(struct sockaddr *)&serv_adr,sizeof(serv_adr))==-1)    

//생성한 소켓에 ip,port,주소체계를 설정해준다.
                printf("bind() error\n");
 if(listen(sock_ser,5)==-1)        //서버에 연결가능도록 해줌.
            printf("listen error\n");
  while(1){
            adr_sz = sizeof(clnt_adr);
            sock_clnt = accept(sock_ser,(struct sockaddr*)&clnt_adr,&adr_sz);//클라이언트의 접속허용
            if(sock_clnt== -1){ //접속이 없다면 아무런 일도 하지않는다.

                   }

                else{                        //접속이 들어온다면,
                        printf("accept !!\n");
                        pid=fork();        //자식프로세스를 생성한 후에,
                        if(pid==0){        //서버소켓의 파일디스크립터를 닫고,
                                close(sock_ser);
                                while((len=read(sock_clnt,buf,100))!=0)    //데이터를 읽어들이고,
                                        write(sock_clnt,buf,len);                //다시클라이언트에게 보내준다.
                                close(sock_clnt);                                //클라이언트 소켓을 소멸시킴.
                                printf("disconnected socket...\n");
                    }
                  else    close(sock_clnt);                            //부모프로세스는 클라이언트의 디스크립터를 닫는다.
                }
        }
        close(sock_ser);        //서버 소켓 소멸.
        return 0;
}

 

 

echo_client.c

 

#include<stdio.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>

int main(int argc,char *argv[])
{
        int sock_clin;
        struct sockaddr_in serv_adr,clnt_adr;
        socklen_t len;
        char buf[100];

 

        sock_clin=socket(PF_INET,SOCK_STREAM,0);    //소켓 생성과 필요한정보할당.
        memset(&clnt_adr,0,sizeof(clnt_adr));
        clnt_adr.sin_family=AF_INET;
        clnt_adr.sin_addr.s_addr=inet_addr(argv[1]);
        clnt_adr.sin_port=htons(atoi(argv[2]));

 

        if(connect(sock_clin,(struct sockaddr *)&clnt_adr,sizeof(clnt_adr))==-1)    

//소켓에 적혀있는 아이피와 포트번호를 보고 접속을 시도함.
        printf("connected error\n");

        printf("Connected!!...\n");
        while(1){
                if((strcmp(buf,"q\n"))==0 || (strcmp(buf,"Q\n")==0))    //q,Q를 입력하면 종료됨.
                break;
                printf("Input Message : ");
                fgets(buf,100,stdin);        //문자열을 입력받고,
                write(sock_clin,buf,sizeof(buf));        //서버에 데이터를 전송,
                read(sock_clin,buf,100);                    //read를 호출하면, 서버로 부터 데이터를 읽어들일 때까지 기다리다가 다음 명령어가 실행되므로, write바로 다음에 read를 쓴다고 해서 서버로부터 응답이 늦게온다고 데이터를 받지 못하는 현상은 일어나지 않는다.
                printf("Message From server : %s\n",buf);    //출력.
        }
        close(sock_clin);            //소켓 소멸.
        return 0;
}

'Programming > Socket' 카테고리의 다른 글

로그파일을 남기는 서버  (0) 2012.05.14
클라이언트 IP 가져오기  (0) 2012.05.14
멀티프로세스 서버  (0) 2012.05.08
소켓의 옵션  (0) 2012.05.07
TCP server 함수호출 순서.  (0) 2012.04.25

멀티 프로세스 서버란, 한번에 하나의 클라이언트에게만 서비스를 제공하는게 아니라 동시에 둘 이상의 클라이언트에게 서비스를 제공하는 서버이다.

 

 

그림처럼 클라이언트의 서비스 요청이 있을 때마다 서버는 자식 프로세스를 생성해서 서비스를 제공한다. 즉, 서비스를 요청하는 클라이언트의 수가 다섯이라면 서버는 추가로 다섯 개의 자식 프로세스를 생성해서 서비스를 제공한다.

이때 자식프로세스를 생성할 때 fork()함수를 사용하는데, fork()함수를 사용하게 되면 부모프로세스의 값을 그대로 복사하기 때문에 파일디스크립터도 복사되서 부모에서 따로 자식에게 소켓의 파일디스크립터를 넘길 필요가 없다.

 

부모 프로세스에서 자식프로세스를 생성하고 파일디스크립터를 넘겨받은 직후의 모습은.

 

이러한 식으로 하나의 소켓에 두개의 파일 디스크립터가 존재하는 경우, 두개의 파일 디스크립터가 모두 소멸되어야 소켓도 소멸된다. 따라서 위와 같은 형태를 유지하면, 자식프로세스가 클라이언트와 연결되어 있는 소켓을 소멸하려 해도 소멸되지 않고 남아있게 된다. 따라서 fork()함수 호출이 후에는 서로에게 상관이 없는 소켓의 파일 디스크립터를 닫아주어야 함.

 

 

 

'Programming > Socket' 카테고리의 다른 글

클라이언트 IP 가져오기  (0) 2012.05.14
멀티프로세스 소스  (0) 2012.05.10
소켓의 옵션  (0) 2012.05.07
TCP server 함수호출 순서.  (0) 2012.04.25
Socket 함수 구조체  (0) 2012.04.24

함수 포인터란?

함수 포인터는 함수의 주소값을 저장하는 포인터이다.

함수의 시작주소값을 가지는 포인터로써, 가르키는 함수의 반환형과 매개변수의 타입이 맞아야만 주소를 저장할 수 있다.

 

int (*ptr)(int)라는 함수 포인터가 있다면,

 

int function(int tmp) 처럼 생긴 포인터를 가르킴. 즉,

 

 

같은 색상의 밑줄끼리는 같은 타입이어야 함수 포인터로 주소값을 저장할 수 있다.

 

함수포인터를 이용한 간단한 예제.

 

실행 화면.

 

 

또한 함수포인터는 typedef 로 미리 선언해 줄수가 있다.

 

#include<stdio.h>

 

typedef int(*ptr)(int)

 

int main()

{

ptr ptr;

 

이런 식으로 미리 선언이 가능하다. 실제로도 이렇게 많이 사용한다고 함.

 

'Programming > C' 카테고리의 다른 글

열거형 enum  (0) 2012.07.09
sscanf , sprintf  (0) 2012.07.06
문자열 붙이기 Strcat()  (0) 2012.07.04
Strtok 문자열 자르기  (0) 2012.06.29
Extern 함수  (0) 2012.05.21

+ Recent posts