EzDoum

찾기
처음으로 | 찾기 | 아카이브 | 글 올리기 | 링크 | 자료실 | 통계 | 연락처 | 자유게시판
이지도움 특집
전체보기
네트워크
TI OMAP35x
TI DaVinci
Analog Blackfin
RobotWar2005
임베디드!
캐쉬의 모든것
메모리 할당 알고리즘
CPU 파이프라이닝
자료구조(Tree)
금융

Login
이름

암호

기억하기


사용자 등록

현재 접속중인 등록 사용자는 0명, 익명 사용자는 2명 입니다.
전체 등록 사용자: 751명

마지막 답장
·libcurl + fuse 조합으로 되는게 많네. (1)
·Linux Ftrace에 관해 (3)
·Android MTP ( Media Transfer Protocol ) (1)
·Lighttpd에 인증을 digest 사용시 IE 오동작 문제? (1)
·Dtrace에 관해 (1)

최근글
·OpenSSL and multi-threads (0)
·ARM 환경에서 OpenCL 사용 (0)
·IoT용 WIFI 모듈 비교 ( MCU ) 클래스 (0)
·Glances - 리눅스 여러 가지 항목을 한 화면에서 모니터링 (0)
·plugin 방식의 로그 분석기 (0)

뜨거운 감자
·나는 인터렉티브한 환경에서 역어셈블 한다. (12)
·GNU REGEX (정규표현식) 프로그래밍 강좌 (7)
·SoCRobotWar 2005 - 신입생 기초 교육자료 (7)
·ASP.NET의 데이터 그리드와 사용자 컨트롤 (7)
·DHTML Editing Control (7)

가장 많이 읽은 글
·[Cache] 2-way Set-Associative 방식이란 무엇일까? (2)
·멀티쓰레드(Pthread) 프로그래밍
·GNU REGEX (정규표현식) 프로그래밍 강좌 (7)
·Sorting Algorithm Animation (2)
·SoCRobotWar 2005 - 신입생 기초 교육자료 (7)

Non-blocking-accept (O_NDELAY , select or poll, alarm)
글쓴이: EzDoum 글쓴날: 2002년 07월 24일 오전 01:04
리눅스



몇가지 방법이 있습니다.


1. Non-blocking-Socket을 사용하는 방법

  1.  
  2. /*
  3. * do a non-blocking-accept
  4. * tested with FreeBSD
  5. * Steve Shah (sshah@planetoid.org)
  6. *
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <unistd.h>
  12. #include <sys/types.h>
  13. #include <sys/param.h>
  14. #include <sys/uio.h>
  15. #include <netinet/in.h>
  16. #include <arpa/inet.h>
  17. #include <netdb.h>
  18. #include <sys/fcntl.h>
  19. #include <sys/socket.h>
  20. #include <sys/time.h>
  21.  
  22. #define NIPQUAD(addr) \
  23.          ((unsigned char *)&addr)[0], \
  24.          ((unsigned char *)&addr)[1], \
  25.          ((unsigned char *)&addr)[2], \
  26.          ((unsigned char *)&addr)[3]
  27.  
  28.  
  29. int main (int argc, char *argv[])
  30. {
  31.     struct sockaddr_in incoming_connection;
  32.     struct sockaddr_in bound_connection;
  33.     int incoming_fd;
  34.     int incoming_socket;
  35.     unsigned int incoming_connection_len;
  36.     struct protoent *tcp;
  37.     int port;
  38.     int errcode;
  39.     int i;
  40.     char buf[80];
  41.     int buflen;
  42.  
  43.     /*
  44.      * Parse command line parameters
  45.      *
  46.      */
  47.  
  48.     if (argc < 2) {
  49.         printf ("Usage: non-blocking-accept <port>\n");
  50.         exit(0);
  51.     }
  52.  
  53.     port = atoi(argv[1]);
  54.     if (port < 1024 || port > 65534) {
  55.         printf ("Port number is out of range.\n");
  56.         exit(0);
  57.     }
  58.  
  59.    
  60.     /*
  61.      * Get TCP's protocol number (needed for the socket() system call)
  62.      *
  63.      */
  64.  
  65.     tcp = getprotobyname("tcp");
  66.     if (tcp == NULL) {
  67.         printf ("Can't get protocol numbers for TCP\n");
  68.         exit(0);
  69.     }
  70.  
  71.  
  72.     /*
  73.      * Create a new socket
  74.      *
  75.      */
  76.  
  77.     incoming_socket = socket(AF_INET, SOCK_STREAM, tcp->p_proto);
  78.     if (incoming_socket < 0) {
  79.         printf ("Can't create a socket\n");
  80.         exit(0);
  81.     }
  82.  
  83.  
  84.     /*
  85.      * Bind to a specific port using the new socket
  86.      *
  87.      */
  88.  
  89.     bound_connection.sin_family      = AF_INET;
  90.     bound_connection.sin_addr.s_addr = htonl(INADDR_ANY);
  91.     bound_connection.sin_port        = htons(port);
  92.  
  93.     /* Note that sockaddr_in is a internet interpretation of sockaddr */
  94.  
  95.     errcode = bind(incoming_socket,
  96.                    (struct sockaddr *)&bound_connection,
  97.                    sizeof (struct sockaddr));
  98.     if (errcode < 0) {
  99.         printf ("Can't bind to port %d", port);
  100.         perror("");
  101.         exit(0);
  102.     }
  103.  
  104.  
  105.     /*
  106.      * Tell us how many incoming connections we can at most queue
  107.      *
  108.      */
  109.  
  110.     errcode = listen(incoming_socket, 128);
  111.     if (errcode == -1) {
  112.         perror ("Can't listen to bound socket");
  113.         exit(0);
  114.     }
  115.  
  116.  
  117.     /*
  118.      * Make socket non-blocking
  119.      *
  120.      */
  121.  
  122.     if (fcntl(incoming_socket, F_SETFL, O_NDELAY) < 0) {
  123.         perror("Can't set socket to non-blocking");
  124.         exit(0);
  125.     }
  126.  
  127.  
  128.     /*
  129.      * Enter the accept loop
  130.      *
  131.      */
  132.  
  133.     incoming_connection_len = sizeof(struct sockaddr_in);
  134.  
  135.     do {
  136.         incoming_fd = accept(incoming_socket,
  137.                              (struct sockaddr *)&incoming_connection,
  138.                              &incoming_connection_len);
  139.         if (incoming_fd != -1) {
  140.             printf ("Accepted connection from %d.%d.%d.%d:%d\n",
  141.                     NIPQUAD(incoming_connection.sin_addr.s_addr),
  142.                     ntohs(incoming_connection.sin_port));
  143.             for (i=10;i>=1;i--) {
  144.                 buflen = snprintf (buf, 80, "%d\n", i);
  145.                 write (incoming_fd, buf, buflen);
  146.                 sleep(1);
  147.             }
  148.             close (incoming_fd);
  149.         } else {
  150.             printf ("Waiting for a connection...\n");
  151.             sleep(1);
  152.         }
  153.     } while (1);
  154.  
  155.     return 0;
  156. }       
  157.  


=========================================================================
2. multiplexing i/o를 사용해서 하는 방법

accept도 결국은 read이벤트에 걸리니까 select리턴 후
ISSET(listen_fd)를 걸었을때 이벤트가 있으면 accept 처리하면 됩니다.
select에서 일정 시간만큼 timeout을 걸어서 종료조건이 되면
서버를 종료 시킬 수 있습니다.

  1.  
  2.    #include <sys/types.h>
  3.    #include <sys/socket.h>
  4.    #include <sys/time.h>
  5.    #include <netinet/in.h>
  6.    #include <netdb.h>
  7.    #include <stdio.h>
  8.    #define TRUE 1
  9.    
  10.    /*
  11.     * This program uses select to check that someone is trying to connect
  12.     * before calling accept.
  13.     */
  14.    
  15.    main()
  16.    {
  17.         int sock, length;
  18.         struct sockaddr_in server;
  19.         int msgsock;
  20.         char buf[1024];
  21.         int rval;
  22.         fd_set ready;
  23.         struct timeval to;
  24.    
  25.         /* Create socket. */
  26.         sock = socket(AF_INET, SOCK_STREAM, 0);
  27.         if (sock < 0) {
  28.              perror("opening stream socket");
  29.              exit(1);
  30.         }
  31.         /* Name socket using wildcards. */
  32.         server.sin_len = sizeof(server);
  33.         server.sin_family = AF_INET;
  34.         server.sin_addr.s_addr = INADDR_ANY;
  35.         server.sin_port = 0;
  36.         if (bind(sock, (struct sockaddr *)&server,
  37.           sizeof(server)) < 0) {
  38.              perror("binding stream socket");
  39.              exit(1);
  40.         }
  41.         /* Find out assigned port number and print it out. */
  42.         length = sizeof(server);
  43.         if (getsockname(sock, (struct sockaddr *)&server,
  44.           &length) < 0) {
  45.              perror("getting socket name");
  46.              exit(1);
  47.         }
  48.         printf("Socket port #%d\n", ntohs(server.sin_port));
  49.    
  50.         /* Start accepting connections. */
  51.         listen(sock, 5);
  52.         do {
  53.              FD_ZERO(&ready);
  54.              FD_SET(sock, &ready);
  55.              to.tv_sec = 5;
  56.              if (select(sock + 1, &ready, (fd_set *)0,
  57.                (fd_set *)0, &to) < 0) {
  58.                   perror("select");
  59.                   continue;
  60.              }
  61.              if (FD_ISSET(sock, &ready)) {
  62.                   msgsock = accept(sock, (struct sockaddr *)0,
  63.                     (int *)0);
  64.                   if (msgsock == -1)
  65.                        perror("accept");
  66.                   else do {
  67.                        memset(buf, 0, sizeof(buf));
  68.                        if ((rval = read(msgsock, buf, 1024)) < 0)
  69.                             perror("reading stream message");
  70.                        else if (rval == 0)
  71.                             printf("Ending connection\n");
  72.                        else
  73.                             printf("-->%s\n", buf);
  74.                   } while (rval > 0);
  75.                   close(msgsock);
  76.              } else
  77.                   printf("Do something else\n");
  78.         } while (TRUE);
  79.         exit(0);
  80.    }
  81.  
  82.  


=========================================================================
3. alarm을 사용
alarm을 사용해서 지정 시간동안 접속이 없으면 accept를
빠져나와서 다른 작업을 하고, 종료 조건이 아니면
다시 알람을 설정하고 잠들면 되겠죠.

  1.  
  2. /******************************************************************/
  3. /* Include files                                                  */
  4. /******************************************************************/
  5. #include <signal.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <errno.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12.  
  13. /******************************************************************/
  14. /* Signal catcher routine.  This routine will be called when the  */
  15. /* signal occurs.                                                 */
  16. /******************************************************************/
  17. void catcher(int sig)
  18. {
  19.    printf("   Signal catcher called for signal %d\n", sig);
  20. }
  21.  
  22. /******************************************************************/
  23. /* Main program                                                   */
  24. /******************************************************************/
  25. int main(int argc, char *argv[])
  26. {
  27.    struct sigaction sact;
  28.    struct sockaddr_in addr;
  29.    time_t t;
  30.    int sd, rc;
  31.  
  32. /******************************************************************/
  33. /* Create an AF_INET, SOCK_STREAM socket                          */
  34. /******************************************************************/
  35.    printf("Create a TCP socket\n");
  36.    sd = socket(AF_INET, SOCK_STREAM, 0);
  37.    if (sd == -1)
  38.    {
  39.       perror("   socket failed");
  40.       return(-1);
  41.    }
  42.  
  43. /******************************************************************/
  44. /* Bind the socket.  A port number was not specified because      */
  45. /* we are not going to ever connect to this socket.               */
  46. /******************************************************************/
  47.    memset(&addr, 0, sizeof(addr));
  48.    addr.sin_family = AF_INET;
  49.    printf("Bind the socket\n");
  50.    rc = bind(sd, (struct sockaddr *)&addr, sizeof(addr));
  51.    if (rc != 0)
  52.    {
  53.       perror("   bind failed");
  54.       close(sd);
  55.       return(-2);
  56.    }
  57.  
  58. /******************************************************************/
  59. /* Perform a listen on the socket.                                */
  60. /******************************************************************/
  61.    printf("Set the listen backlog\n");
  62.    rc = listen(sd, 5);
  63.    if (rc != 0)
  64.    {
  65.       perror("   listen failed");
  66.       close(sd);
  67.       return(-3);
  68.    }
  69.  
  70. /******************************************************************/
  71. /* Set up an alarm that will go off in 5 seconds.                 */
  72. /******************************************************************/
  73.    printf("\nSet an alarm to go off in 5 seconds.  This alarm will cause the\n");
  74.    printf("blocked accept() to return a -1 and an errno value of EINTR.\n\n");
  75.    sigemptyset(&sact.sa_mask);
  76.    sact.sa_flags = 0;
  77.    sact.sa_handler = catcher;
  78.    sigaction(SIGALRM, &sact, NULL);
  79.    alarm(5);
  80.  
  81. /******************************************************************/
  82. /* Display the current time when the alarm was set                */
  83. /******************************************************************/
  84.    time(&t);
  85.    printf("Before accept(), time is %s", ctime(&t));
  86.  
  87. /******************************************************************/
  88. /* Call accept.  This call will normally block indefinitely,      */
  89. /* but because we have an alarm set, it will only block for       */
  90. /* 5 seconds.  When the alarm goes off, the accept call will      */
  91. /* complete with -1 and an errno value of EINTR.                  */
  92. /******************************************************************/
  93.    errno = 0;
  94.    printf("   Wait for an incoming connection to arrive\n");
  95.    rc = accept(sd, NULL, NULL);
  96.    printf("   accept() completed.  rc = %d, errno = %d\n", rc, errno);
  97.    if (rc >= 0)
  98.    {
  99.       printf("   Incoming connection was recevied\n");
  100.       close(rc);
  101.    }
  102.    else
  103.    {
  104.       perror("   errno string");
  105.    }
  106.  
  107. /******************************************************************/
  108. /* Show what time it was when the alarm went off                  */
  109. /******************************************************************/
  110.    time(&t);
  111.    printf("After accept(), time is %s\n", ctime(&t));
  112.    close(sd);
  113.    return(0);
  114. }


[분류: 리눅스 인쇄용 페이지 본문 email로 보내기 ]

<  축구관련 사이트 모음! | Linux I/O Models  >

답장 쓰기
글을 올리시려면 로그인 (사용자 등록) 하셔야 합니다.

검색
Google

분류
·공지 (6)
·인터넷 (87)
·하드웨어 (260)
·C/C++ (65)
·어셈블리 (7)
·리눅스 (136)
·리눅스 커널 (67)
·윈도우즈 (25)
·데이터베이스 (20)
·보안 (16)
·.NET (25)
·그래픽 (13)
·책소개 (42)
·호기심 천국 (80)
·잡담 (111)
·사랑 (3)

전체 본문수: 963
전체 답장수: 525


분류 : 리눅스
최근글
최근글
가장 많이 읽은 글
·멀티쓰레드(Pthread) 프로그래밍 (0)
뜨거운 감자
·GNU REGEX (정규표현식) 프로그래밍 강좌 (7)

EzDoum투표
이지도움 어때요?
이게 뭐야. 다시 안올란다. --;
아이 좋아라~ +_+;
관심없다.
먼가는 있는거 같은데 뭐하는 곳이지?
기타 (자유게시판에 글로 남겨 주세요)
[ 결과 | 투표 ]

랜덤 링크
http://kldp.net


 Home ^ BACK TO TOP ^ EzDoum - 도움이 필요하세요~??
 Powered by KorWeblog 1.5.8 Copyleft © 2001 EzDoum, 관리자: EzDoum