높은 동시 처리의 사용자 지정 프로토콜 서버를 기반으로 : 다중 스레드 모델

https://www.cnblogs.com/lan0725/p/11634267.html  간단하게 처리, 서버는 클라이언트 시간에 반환하고 소켓을 닫습니다.

당신은 양방향 통신을 할 경우, 서버는 클라이언트가 서버에 데이터를 전송하지 않는 경우, 읽기 함수를 호출하지만, 기본이 차단 읽을 바인딩, 메인 쓰레드가 차단되어, 다른 클라이언트가 성공적으로 연결할 수 없습니다. 이 높은 동시성 문제를 처리해야합니다.

높은 동시 서버를 다루는 세 가지 방법

  1. 멀티 프로세스  https://www.cnblogs.com/lan0725/p/11634709.html
  2. 멀티 스레딩  https://www.cnblogs.com/lan0725/p/11639142.html
  3.  I / O 멀티플렉서

 설정의 메이크 파일 디렉토리가있는 여러 프로세스에 설명되어 있습니다  https://www.cnblogs.com/lan0725/p/11634709.html

멀티 스레드 멀티 프로세스의 효율성보다 훨씬 높은,하지만 스레드의 대부분은 프로세스 공간, 멀티 프로세스 복사 공간을 공유하기 때문에 또한함으로써 시스템 오버 헤드를 줄일 수있다.

  1. 메인 쓰레드는 책임 accepte이다 후 별도의 속성을 자식 스레드를 만들 수 있습니다.
  2. 각 클라이언트는이 스레드에서 양방향 통신을 수행하는 별도의 속성 스레드를 유지하기 위해 연결되어 있습니다. 많은 클라이언트 연결, 아이 thread의 수는 열 방법 때문입니다.

같은 클라이언트 및 멀티 프로세스.

주요 기능은 복구 스레드에 가입 메인 스레드를 기다릴 필요가 없습니다, 차이를 받아 별도의 스레드를 생성 할 경우에만 사실이 있습니다. 특정 차이를 do_something 없습니다.

멀티 스레드 서버 2_echo_multhread_tcp_server.c :

#INCLUDE <SYS / socket.h> 
#INCLUDE <SYS / types.h> 
#INCLUDE <STDIO.H> 
#INCLUDE <stdlib.h> 
사용법 #include <unistd.h> 
#INCLUDE <signal.h>를 소스 안에서 포함하면 
#INCLUDE <시각 .H> 
#INCLUDE < 문자열 .H> 
#INCLUDE <netdb.h>에 
#INCLUDE <ARPA / inet.h> 
사용법 #include " msg.h " 
#INCLUDE <errno.h> 
#INCLUDE <pthread.h를>

#DEFINE의 SERVER_PORT 8888
 #DEFINE의 LISTEN_QUEUE_SISE (10)

INT는 socketfd;

보이드 signal_handler ( INT의 SIGNO)
{
    경우 (SIGNO == SIGINT)
    {
        의 printf ( " 이 serveice 근접 \ n을 " );
        확대 (socketfd);
        출구 ( 1 );
    }
}

보이드 print_clientinfo ( INT의 FD, CONST   *의 유형)
{
    구조체 를 sockaddr_in 요지;
    memset 함수 ( 및 ADDR, 0 , 는 sizeof (ADDR));
    socklen_t이 LEN = 를 sizeof (ADDR);

    경우 (getpeername는 (FD ( 구조체 SOCKADDR의 *) ADDR, LEN) < 0 )
    {
        perror는 ( " getpeername는 에러 " );
        반환 ;
    }

    숯불 ipstr을 [ 16 ];
    memset 함수 (ipstr, 0 , sizeof의 (ipstr));
     // 소수점 점선 네트워크 바이트 순서에서 어드레스 변환 
    inet_ntop (AF_INET, addr.sin_addr.s_addr, ipstr, sizeof의이 (ipstr));

    의 printf ( " % S (%의 D) %의 \ n " , ipstr, ntohs (addr.sin_port) 형);
}

보이드 do_something ( INT의 FD)
{
     버프 [ 1024 ];
    하지만 ( 1 )
    {
        // 클라이언트에 의해 보내진 내용 읽기 
        memset 함수 (BUFF, 0 , sizeof의 (BUFF))를;
        이 size_t 크기 = read_msg (FD, 버프 를 sizeof (광));
        경우 (크기 < 0 )
        {
            // 프로토콜 에러 주요 서브 프로세스의 후방 단부 밖으로 동안 
            perror는 ( " read_msg 에러 " )
             BREAK ;
        }
        다른  경우 (사이즈 == 0 )
        {
            / * 연결 클라이언트는 자식 스레드를 종료 할 동안 밖으로 전화를 끊었
             * * / 
            휴식 ;
        }
        
        의 printf ( " recev 클라이언트 : %의 \ 없음 " , 버프);

        // 위로 기록 데이터 
        IF (FD write_msg (BUFF, 는 sizeof (BUFF)) < 0 )
        {
            경우 (errno를 == EPIPE)
            {
                / * 클라이언트 연결이 끊어  
                 * SIGPIPE 신호를 생성 
                 * 오류는 EPIPE로 설정
                 * 또한이 결정 SIGPIPE errno를 캡처 할 수 있습니다.
                 * 일반적 파이프 버스트라고도
                 자식 스레드가 종료됩니다하면서 * 밖으로 이동
                 * * / 
                휴식 ;
            }
            

            perror는 ( " write_msg 에러 " );
        }
    }
}

보이드 * threadWork ( 공극 * ARG)
{
    INT FD = ( INT ) ARG;
    print_clientinfo (FD, " 연결 " );
    do_something (FD);
    print_clientinfo (FD, " 폐쇄 " );
    확대 (FD);
    반환 NULL을;
}


INT 본체 ( 의 INT 는 argc,  CONST * 는 argv [])
{
    IF (신호 (SIGINT, signal_handler) == SIG_ERR)
    {
        perror는 ( " 신호 에러 " );
        출구 ( 1 );
    }

    // 1 sokect
     // AF_INET의 IPv4의
     // SOCK_STREAM TCP 
    경우 ((socketfd = 소켓 (AF_INET, SOCK_STREAM, 0 )) < 0 )
    {
        perror는 ( " 소켓 오류 " );
        출구 ( 1 );
    }

    // 2는 바인드 로컬 주소와 포트 결합 
    구조체 를 sockaddr_in ServerAddr을;
    memset 함수 ( & serveraddr, 0 , 는 sizeof (serveraddr));
    serveraddr.sin_family = AF_INET; // 의 IPv4 
    serveraddr.sin_port = htons (SERVER_PORT) // 포트 
    serveraddr.sin_addr.s_addr = htonl (INADDR_ANY); // 카드에 대한 요청에 응답하여 
    IF (바인드 (socketfd ( 구조체 의 SOCKADDR *)를 ServerAddr & sizeof의 (ServerAddr)) < 0 )
    {
        perror는 ( " 바인드 에러 " );
        출구 ( 1 );
    }

    // (가) 시스템들을 알려 듣고 3 시작 클라이언트 준비 큐 연결의 연결 수락 
    IF (청취 (socketfd, LISTEN_QUEUE_SISE을) < 0 )
    {
        perror는 ( " 오류를 듣고 " );
        출구 ( 1 );
    }

    가 pthread_t 스레드;
    // 메인 스레드를 필요로하지 않는 속성에 관련된 분리 pthread_join을 하위 스레드 회복 호출 설정 
    pthread_attr_t의 ATTR을;
    pthread_attr_init ( & ATTR);
    pthread_attr_setdetachstate ( & ATTR, PTHREAD_CREATE_DETACHED);
    INT의 retno;
    하지만 ( 1 )
    {    
        // . 제 4 큐로부터 수락 
        INT clientfd = 수락 (socketfd, NULL NULL);
         IF (clientfd < 0 )
        {
            perror는 ( " 오류를 받아 " );
            계속 ;
        }
        // 5 속성 서브 글 읽기 / 쓰기 할 별도의 서브 스레드를 생성하는 
        IF ((= retno는 pthread_create (스레드, ATTR,
            threadWork ( 무효 *) clientfd))! = 0 )
        {
            의 printf ( " 오류 nuber %의 D, S의 % \ 없음 " , retno, strerror는 (retno));
            확대 (clientfd);
            계속 ;
        }

    }
    
    // 부동산 스레드 파괴 
    pthread_attr_destroy ( ATTR);
     // 6 사용 닫기 
    사용 닫기 (socketfd가)
     반환  0 ;
}
코드보기

 

추천

출처www.cnblogs.com/lan0725/p/11639142.html