https://www.cnblogs.com/lan0725/p/11634267.html 간단하게 처리, 서버는 클라이언트 시간에 반환하고 소켓을 닫습니다.
당신은 양방향 통신을 할 경우, 서버는 클라이언트가 서버에 데이터를 전송하지 않는 경우, 읽기 함수를 호출하지만, 기본이 차단 읽을 바인딩, 메인 쓰레드가 차단되어, 다른 클라이언트가 성공적으로 연결할 수 없습니다. 이 높은 동시성 문제를 처리해야합니다.
높은 동시 서버를 다루는 세 가지 방법
- 멀티 프로세스 https://www.cnblogs.com/lan0725/p/11634709.html
- 멀티 스레딩 https://www.cnblogs.com/lan0725/p/11639142.html
- I / O 멀티플렉서
설정의 메이크 파일 디렉토리가있는 여러 프로세스에 설명되어 있습니다 https://www.cnblogs.com/lan0725/p/11634709.html
멀티 스레드 멀티 프로세스의 효율성보다 훨씬 높은,하지만 스레드의 대부분은 프로세스 공간, 멀티 프로세스 복사 공간을 공유하기 때문에 또한함으로써 시스템 오버 헤드를 줄일 수있다.
- 메인 쓰레드는 책임 accepte이다 후 별도의 속성을 자식 스레드를 만들 수 있습니다.
- 각 클라이언트는이 스레드에서 양방향 통신을 수행하는 별도의 속성 스레드를 유지하기 위해 연결되어 있습니다. 많은 클라이언트 연결, 아이 thread의 수는 열 방법 때문입니다.
같은 클라이언트 및 멀티 프로세스.
주요 기능은 복구 스레드에 가입 메인 스레드를 기다릴 필요가 없습니다, 차이를 받아 별도의 스레드를 생성 할 경우에만 사실이 있습니다. 특정 차이를 do_something 없습니다.
멀티 스레드 서버 2_echo_multhread_tcp_server.c :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ; }