본문으로 바로 가기

약 18개월 전, 저는 OpenVOS 릴리스 17.1에서 accept 함수의 작동 방식이 어떻게 변경되었는지에 대해 블로그 글을 쓴 적이 있습니다. 당시 제가 언급하지 않았던 점은 이러한 변경 사항이 애플리케이션 코드가 POSIX 기반일 때만 적용된다는 사실이었습니다. 다시 정리하자면, 17.1 이전에는 서버 애플리케이션 코드가 accept 루틴을 호출한 경우에만 STCP가 클라이언트의 연결 요청에 응답했습니다. 코드가 accept를 호출하지 않았다면 클라이언트의 연결 요청은 큐에 들어갔지만 응답을 받지 못했습니다. 애플리케이션이 accept를 호출하면 STCP는 연결 응답을 보냈습니다. 클라이언트가 여전히 대기 중이라면 그 시점에 연결이 완료됩니다. 클라이언트가 이미 연결을 포기한 상태라면 연결 응답에 대해 리셋(reset)으로 응답하고, STCP는 해당 연결을 버리며 accept는 (블로킹 모드라고 가정할 때) 중단된 상태로 다른 연결을 기다리게 됩니다.

그림 1은 이러한 시나리오를 보여줍니다. 왼쪽 정렬된 텍스트 줄은 서버 애플리케이션의 상태 메시지이며, 들여쓰기된 packet_monitor 줄(약간 수정됨)은 클라이언트 활동의 결과입니다. 애플리케이션(acceptTestnoPosix)이 시작되어 포트 12345에서 리스닝을 시작하고, 리스닝이 시작되면 300초 동안 대기 상태에 들어갑니다. 그런 다음 클라이언트는 Syn(S) 플래그가 설정된 TCP 세그먼트를 포트 12345로 전송하여 연결을 시도합니다. 클라이언트는 세 번 시도한 후 포기합니다. 300초가 지나면 애플리케이션이 대기 상태에서 깨어나 accept를 호출합니다. STCP 스택은 Syn 및 Ack(SA) 플래그가 설정된 TCP 세그먼트를 클라이언트에 응답으로 보냅니다. 클라이언트는 더 이상 해당 연결에 대한 기록을 가지고 있지 않으므로 Reset(R)을 전송하고, 이 시점에서 STCP는 차단됩니다. 소켓이 비차단 모드였다면 accept는 EAGAIN 오류를 반환했을 것입니다.

acceptTestnoPosix 12345
acceptTestnoPosix 12345 실행 중
300초 동안 대기 중

  11:04:45.923 R TCP 164.152.77.50   164.152.77.217  11071  12345 S
  11:04:48.925 R TCP 164.152.77.50   164.152.77.217  11071  12345 S
  11:04:54.937 R TCP 164.152.77.50   164.152.77.217  11071  12345 S

포트 번호 12345에서 연결 수신 준비 완료
  11:09:41.852 T TCP 164.152.77.217  164.152.77.50   12345  11071 SA 
  11:09:41.854 R TCP 164.152.77.50   164.152.77.217  11071  12345 R

그림 1 – 17.1 이전 버전 또는 17.1 이후의 비-POSIX 버전 허용

 

애플리케이션이 POSIX 기반인 경우 상황은 달라집니다(그림 2). STCP는 연결 요청(S)에 즉시 응답하여 연결 세션(SA)을 생성합니다. 그런 다음 300초가 지나면 애플리케이션이 깨어나 accept를 호출하고, STCP는 수락된 소켓을 반환합니다.

acceptTestwithPosix 12345
acceptTestnoPosix 12345 실행 중
300초 동안 대기 중

  10:58:43.962 R TCP 164.152.77.50   164.152.77.217  11024  12345 S
  10:58:43.964 T TCP 164.152.77.217  164.152.77.50   12345  11024 SA 
  10:58:43.964 R TCP 164.152.77.50   164.152.77.217  11024  12345 A

포트 번호 12345에서 연결을 수락할 준비가 되었습니다
연결 수락됨

그림 2 – POSIX 기반 게시물 허용 17.1

 

이러한 동작 차이는 치명적일 수 있습니다. 클라이언트가 연결을 설정한 후 서버 애플리케이션으로부터 응답을 기다리는 경우, 애플리케이션이 실제로 accept를 호출하기 전에 시간 초과가 발생하여 연결이 종료될 수 있습니다.

POSIX를 사용하여 애플리케이션을 어떻게 구축하나요? 먼저 다음 줄을

#define _POSIX_C_SOURCE 200112L

응용 프로그램 소스 코드의 첫 번째 줄에 위치해야 합니다. 두 번째는 라이브러리 경로입니다.

(master_disk)>system>posix_object_library

STCP 라이브러리 뒤쪽과 C 라이브러리 앞쪽에 객체 라이브러리 경로에 포함되어야 합니다.

이 작업이 수행되었는지 어떻게 알 수 있을까요? display_program_module -object_dirs 명령어를 사용하여 해당 애플리케이션이 바인딩된 오브젝트 라이브러리를 확인해 볼 수 있습니다.

display_program_module acceptTestwithPosix -object_dirs      
     %azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm 

객체 디렉터리 맵:

    11  검색 디렉터리
     0  비검색 디렉터리
    총 11개 디렉터리

   DTC  디렉터리 경로

     1  %azvos#m17_mas>SysAdmin>Noah_Davids>temp
     2  %azvos#m17_mas>system>stcp>object_library\n
     3  %azvos#m17_mas>system>stcp>object_library>socket\n
     4  %azvos#m17_mas>system>stcp>object_library>net
     5  %azvos#m17_mas>system>stcp>object_library>common
     6  %azvos#m17_mas>system>posix_object_library
     7  %azvos#m17_mas>system>c_object_library
     8  %azvos#m17_mas>system>object_library
     9  %azvos#m17_mas>opt>apache>lib
    10  %azvos#m17_mas>opt>openssl>lib
    11  %azvos#m17_mas>opt>mysql>lib>mysql

하지만 이 방법만으로는 #define이 소스 코드의 일부인지 알 수 없습니다.

코드를 실행할 수 있다면 소켓 플래그를 확인해 볼 수 있습니다. POSIX 기반 프로그램의 경우 SF_POSIX 소켓 플래그가 설정되어 있을 것입니다. 예를 들어, acceptTestnoPosix, acceptTestwithPosix, acceptTestwithPosixPathOnly라는 세 가지 프로그램이 있습니다. 마지막 프로그램의 경우 라이브러리 경로에 >system>posix_object_library 디렉터리가 포함되어 있었지만, 소스 코드에는 #define 문이 포함되어 있지 않았습니다. 이는 유효하지 않은 조합으로 간주된다는 점에 유의하십시오. POSIX 라이브러리와 바인딩되었고 코드에 POSIX_SOURCE #define 문이 포함된 애플리케이션만이 SF_POSIX 플래그가 설정된 소켓을 생성했습니다.

acceptTestnoPosix.pm 12345          
acceptTestnoPosix 12345 실행 중
300초 동안 대기 중
               as:  match posix; dump_stcbq -full -lport 12345       
               as:
acceptTestwithPosix.pm 12345\
acceptTestnoPosix 12345 실행 중\
300초 동안 대기 중\
               as:  match posix; dump_stcbq -full -lport 12345
                                                   SF_POSIX
               as:  
acceptTestwithPosixPathOnly.pm 12345
acceptTestnoPosix 12345 실행 중
300초 동안 대기 중
               as:  match posix; dump_stcbq -full -lport 12345
               as:

네 번째 가능성은 소스 코드에 #define이 포함되어 있지만 posix_object_library가 사용되지 않은 경우입니다. 이 경우 소켓 루틴은 오류를 반환합니다.

acceptTestwithPosixDefineOnly 12345
acceptTestnoPosix 12345 실행 중
acceptTestnoPosix: 리스닝 소켓을 생성할 수 없음: 애플리케이션이  
+  잘못 빌드됨: C 런타임보다 먼저 POSIX 런타임을 검색해야 합니다.

모든 STCP 명령어와 유틸리티는 POSIX 표준에 따라 구현되었으며, 여러분이 개발하는 모든 애플리케이션에서도 POSIX를 사용할 것을 강력히 권장합니다.

© 2024 Stratus Technologies.