programing

SO_REUSEADDR과 SO_REUSEPORT의 차이점은 무엇입니까?

yellowcard 2023. 4. 20. 20:46
반응형

SO_REUSEADDR과 SO_REUSEPORT의 차이점은 무엇입니까?

man pages 소켓옵션용 SO_REUSEADDR ★★★★★★★★★★★★★★★★★」SO_REUSEPORT운영체제에 따라 다르며 매우 혼란스러운 경우가 많습니다.SO_REUSEPORTWWW에는 이 주제에 관한 모순되는 정보가 가득합니다.또한 특정 운영체제의 1소켓 실장에만 해당하는 정보를 찾을 수 있습니다.이 정보는 텍스트에 명시되어 있지 않을 수도 있습니다.

럼은 정확히 의미일까요?SO_REUSEADDRSO_REUSEPORT

★★★★★★★★★★★★★★가 없는 시스템SO_REUSEPORT★★★★★★★★★★★★★★★★★★★?

또, 다른 operating system으로 어느쪽인가를 사용하고 있는 경우, 예상되는 동작은 무엇입니까?

휴대성이라는 멋진 세계에 오신 것을 환영합니다.오히려 부족할 수도 있습니다.이 두 가지 옵션에 대한 자세한 분석을 시작하고 서로 다른 운영체계가 어떻게 이들 옵션을 처리하는지 자세히 살펴보기 전에 BSD 소켓 구현은 모든 소켓 구현의 어머니라는 점에 유의해야 합니다.기본적으로 다른 모든 시스템은 특정 시점(또는 적어도 그 인터페이스)에 BSD 소켓 구현을 복사한 후 자체적으로 BSD 소켓 구현을 발전시키기 시작했습니다.물론 BSD 소켓 구현도 동시에 진화했기 때문에 BSD 소켓을 복사한 시스템은 나중에 BSD 소켓을 복사한 시스템에는 없는 기능을 갖게 되었습니다.BSD 소켓의 실장을 이해하는 것은 다른 모든 소켓의 실장을 이해하는 열쇠이므로 BSD 시스템의 코드를 쓰고 싶지 않은 경우에도 BSD 소켓의 실장에 대해 읽어보십시오.

이 두 가지 옵션을 검토하기 전에 알아야 할 몇 가지 기본 사항이 있습니다.TCP/UDP 접속은, 다음의 5 개의 값의 태플에 의해서 식별됩니다.

{<protocol>, <src addr>, <src port>, <dest addr>, <dest port>}

이러한 값의 중복되지 않는 조합에 의해서 접속이 식별됩니다.그 결과, 2개의 접속이 같은5개의 값을 가질 수 없습니다.그렇지 않으면 시스템은 이러한 접속을 구별할 수 없게 됩니다.

될 때 됩니다.socket()포토는, 송신원주소는, 「송신원주소나 포토설정되어 .bind(), 행선지 주소나 포토는, 행선지 주소나 가 설정되어 있습니다.connect()할 수 있습니다.UDP는 무접속 프로토콜이므로 UDP 소켓을 연결하지 않고도 사용할 수 있습니다.단, 접속은 허용되며 경우에 따라서는 코드와 일반적인 애플리케이션 설계에 매우 유리합니다. UDP 소켓을할 수 입니다.바인딩되지 않은 TCP 소켓도 마찬가지이며 연결되기 전에 자동으로 바인딩됩니다.

을 포트 에 수 .0 포트의 '어느 포트'라는 뜻의 '어느 포트'.소켓을 기존의 모든 포트에 실제로 바인드할 수는 없기 때문에 이 경우 시스템은 특정 포트 자체를 선택해야 합니다(통상 사전에 정의된 OS 고유의 송신원포트 범위).주소」(「를 지정할 수 있습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★0.0.0.0 및 IPv4 의 ::IPv6 「」).포트의 경우와 달리 소켓은 실제로 "모든 로컬인터페이스의 모든 송신원 IP 주소"를 의미하는 "임의의 주소"에 바인딩될 수 있습니다.소켓을 나중에 연결할 경우 소켓은 연결할 수 없고 동시에 로컬 IP 주소에 바인딩되기 때문에 시스템은 특정 소스 IP 주소를 선택해야 합니다.행선지 주소와 라우팅 테이블의 내용에 따라, 시스템은 적절한 송신원주소를 선택해, 「임의」바인딩을 선택한 송신원IP 주소

디폴트에서는, 송신원주소와 송신원포토의 같은 편성에 2개의 소켓을 바인드 할 수 없습니다.송신원포트가 다른 한, 송신원주소는 실제로는 무관합니다. " " "socketA로로 합니다.ipA:portA ★★★★★★★★★★★★★★★★★」socketB로로 합니다.ipB:portB은, 「」의 경우입니다.ipA != ipB「 「」가 입니다.portA == portB를 들어socketA 서버 에 .192.168.0.1:21 ★★★★★★★★★★★★★★★★★」socketB는, 서버 에 속해 , 「」에 바인드 있습니다.10.0.0.1:21양쪽 바인딩이 성공합니다.로 "의 주소에 수 이 에 되어 0.0.0.0:21는 기존의 되어 경우 은 포트 "D" 에 할 수 .21에 바인드 「IP」로 합니다.0.0.0.0IP를 사용하다

지금까지 말한 내용은 모든 주요 운영 체제에서 거의 동일합니다.주소의 재사용이 이루어지면, OS에 고유의 것이 생기기 시작합니다.먼저 BSD부터 시작합니다.상기 말했듯이 BSD는 모든 소켓 구현의 어머니입니다.

BSD

SO_REUSEADDR

ifSO_REUSEADDR는 바인드 전에 소켓 상에서 이니블로 되어 있습니다.송신원주소와 포토의 완전히 같은 편성에 바인드 되어 있는 다른 소켓과의 경합이 없는 한, 소켓을 정상적으로 바인드 할 수 있습니다.이게 예전과 어떻게 다른지 궁금하실 수도 있습니다.키워드는 "정확히"입니다. SO_REUSEADDR는 주로 경합을 검색할 때 와일드카드주소("임의의 IP 주소")의 처리 방법을 변경합니다.

SO_REUSEADDR , 「」socketA로로 합니다.0.0.0.0:21으로 바인딩을 합니다.socketB로로 합니다.192.168.0.1:21EADDRINUSE은 ' 주소'를 의미하므로 는 이 되고 있는 되며, 에는 0.0.0.0이 포함됩니다192.168.0.1 ㅇㅇㅇㅇㅇㅇ로요SO_REUSEADDR할 것이다0.0.0.0 ★★★★★★★★★★★★★★★★★」192.168.0.1완전히 같은 주소가 아닙니다.하나는 모든 로컬주소의 와일드카드이고 다른 하나는 매우 특정 로컬주소입니다.위의 문장은 순서에 관계없이 참입니다.socketA ★★★★★★★★★★★★★★★★★」socketB되어 있다SO_REUSEADDRSO_REUSEADDR이치노

보다 나은 개요를 제공하기 위해 여기 표를 만들고 가능한 모든 조합을 나열해 보겠습니다.

SO_REUSEADDR 소켓A 소켓B 결과---------------------------------------------------------------------ON/OFF 192.168.0.1:21 192.168.0.1:21 오류(EADDRINUSE)ON/OFF 192.168.0.1:21 10.0.1:21 OKON/OFF 10.0.1:21 192.168.0.1:21 OKOFF 0.0.0:21 192.168.1.0:21 오류(EADDRINUSE)OFF 192.168.1.0:21 0.0.0:21 오류(EADDRINUSE)ON 0.0.0:21 192.168.1.0:21 OKON 192.168.1.0:21 0.0.0:21 OKON/OFF 0.0.0:21 0.0.0:21 오류(EADDRINUSE)

는 the음음음음음음음음음음음음음 that that that that that that that that that that that that that that 라고 가정하고 있습니다.socketA은 이미 의 주소에 되어 .socketA , , , 「 」socketB 「」, 「」의 를 취득했을 경우.SO_REUSEADDR 여부에 으로 '설정'에 .socketBResult는, 의 입니다.socketB 첫 에 .라고 적혀 있는 ON/OFF의 값, " " "SO_REUSEADDR결과와는 무관합니다.

네, 네.SO_REUSEADDR와일드카드 주소에 영향을 줍니다.가 있는 은 아닙니다하지만 그것이 가진 유일한 영향은 아니다. 잘 , 이 '보다 낫다'를 사용하는 이기도 합니다.SO_REUSEADDR서버 프로그램에 포함되어 있습니다.이 옵션을 사용하는 다른 중요한 방법에서는 TCP 프로토콜의 작동 방식을 자세히 살펴봐야 합니다.

TCP 소켓이 닫히면 보통 3방향 핸드쉐이크가 실행됩니다.시퀀스는 라고 불립니다.여기서의 문제는, 그 시퀀스의 마지막 ACK가 다른 쪽에 도달했을 가능성이 있거나 도착하지 않았을 가능성이 있으며, 도달했을 경우에만 다른 쪽도 소켓이 완전히 닫힌 것으로 간주된다는 것입니다.일부 리모트피어(peer)에 의해 오픈된 것으로 간주되는 주소+포트의 조합을 재사용하지 않도록 하기 위해 시스템은 마지막 송신 후 소켓을 즉시 비활성 상태로 간주하지 않습니다.ACK 소켓을 으로 '소켓'이라고로 만듭니다.TIME_WAIT. 몇 분 동안 이 상태로 있을 수 있습니다(시스템에 의존한 설정).대부분의 시스템에서는 대기시간을 유효하게 하고 langer time을 01로 설정하면 이 상태를 회피할 수 있지만, 이것이 항상 가능한 것은 아닙니다.시스템이 이 요구를 항상 수용한다고 해도 소켓이 리셋()RST에 의해 닫히는 것은 항상 좋은 생각은 아닙니다.란제리 타임에 대해 더 알고 싶다면, 이 주제에 대한 제 답변을 보세요.

을 상태 그대로 TIME_WAITSO_REUSEADDR되어 있지이 「CHANGE」상태입니다.소켓은 스테이트입니다.TIME_WAIT는, 아직 송신원주소와 포토에 바인드 되어 있는 것으로 간주되어 새로운 소켓을 같은 주소 및 포토에 바인드 하는 어떠한 시도도, 소켓이 정말로 닫힐 때까지 실패합니다.따라서 소켓을 닫은 후 바로 소켓의 소스 주소를 다시 바인딩할 수 있다고 생각하지 마십시오.이치 「」의 경우는, 「」입니다.SO_REUSEADDR 소켓에 , 및에 되어 있는 상태로 .TIME_WAIT는, 이미 「반쪽 정지」상태로 되어 있기 때문에, 간단하게 무시됩니다.소켓은 문제없이 같은 주소에 바인드 할 수 있습니다.이 경우 다른 소켓의 주소와 포트가 완전히 같을 수 있습니다.을 에 있는 및 하는 .TIME_WAIT상태는 다른 소켓이 아직 "작동 중"인 경우 예상치 못한, 대개 바람직하지 않은 부작용을 가질 수 있지만, 이는 이 답변의 범위를 벗어나며 다행히 그러한 부작용은 실제로 드물다.

할 있습니다.SO_REUSEADDR. 된 모든 재사용이 한 위에 기술된 모든 내용은 바인드하는 소켓에서 주소 재사용이 활성화되어 있는 한 작동합니다., 즉 있거나 하지 않습니다.TIME_WAIT바인딩 시 이 플래그가 설정되어 있습니다.는 " " "만을 합니다.SO_REUSEADDR bind()모든 는 이 플래그는 .call, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada, ada ada, ada,

SO_REUSEPORT

SO_REUSEPORT의 사람들이 이다.SO_REUSEADDR본적으, to to to to to,SO_REUSEPORT임의의 수의 소켓을 동일한 송신원주소와 포트에 바인드할 수 있습니다., 모든 선행 바인딩된 소켓이 동일한 경우SO_REUSEPORT없는 SO_REUSEPORT이 다른 소켓이 같은 주소와 포트에 바인드할 수 없습니다.SO_REUSEPORT첫 번째 소켓이 바인딩을 다시 해제할 때까지 설정 여부를 지정합니다.의 경우와 SO_REUSEADDR 핸들링SO_REUSEPORT는 현재 이 "Socket"을 가지고 있는지 만 아니라 "Socket"을 가지고 있는지 확인합니다.SO_REUSEPORT되지만, 및가 경합하는 에 「」가 있는 합니다.SO_REUSEPORT이치노

SO_REUSEPORT는 의미하지 .SO_REUSEADDR에 「」가 , 「」라고 하는 SO_REUSEPORT바인드되어 있고 다른 소켓이 있을 때 설정됩니다.SO_REUSEPORT 및된 것이지만, 다른 이 이미 하고 있고, 이 "Deaking" 에 있는 합니다.이것은 예상된 것이지만, 다른 소켓이 이미 정지하고 있는 경우에도 실패합니다.TIME_WAIT 및 수 .TIME_WAIT상태에는 다음 중 하나가 필요합니다.SO_REUSEADDR 또는 그 으로 SO_REUSEPORT바인드하기 전에 양쪽 소켓에 설정되어 있어야 합니다.물론 둘 다 설정할 수 있지만SO_REUSEPORT ★★★★★★★★★★★★★★★★★」SO_REUSEADDR , on에있있 , , , , , , , ,.

SO_REUSEPORT보다 늦게 추가된 것 이외에는SO_REUSEADDR그 때문에, 이 옵션이 추가되기 전에 BSD 코드를 「포킹」한 다른 시스템의 많은 소켓 실장에서는 찾을 수 없습니다.또, 이 옵션이 추가되기 전에는, BSD내의 같은 소켓주소에 2개의 소켓을 바인드 하는 방법이 없었습니다.

Connect() EADDRINUSE를 반환하시겠습니까?

대부분의 사람들은 그것을 안다.bind()에러로 인해 실패할 수 있습니다.EADDRINUSE그러나, 당신이 주소 재사용을 가지고 장난을 치기 시작하면, 당신은 이상한 상황에 직면할 수 있습니다.connect()이 에러에 의해서도 실패합니다.어떻게 이럴 수 있죠?소켓에 접속이 추가되는 리모트주소가 어떻게 이미 사용되고 있을까요?여러 소켓을 정확히 같은 리모트주소에 접속하는 것은 지금까지 문제가 되지 않았습니다만, 여기서 문제가 되는 것은 무엇입니까?

답신 맨 위에 말씀드렸듯이, 연결은 5개의 값의 튜플로 정의됩니다.기억하시죠?또, 이 5개의 값은 일의여야 합니다.그렇지 않으면 시스템이 2개의 접속을 구별할 수 없게 됩니다.주소 재사용을 사용하면 동일한 프로토콜의 두 소켓을 동일한 소스 주소와 포트에 바인딩할 수 있습니다.즉, 이들 5개의 값 중3개는 이 2개의 소켓에 대해 이미 같은 값입니다.이 시점에서, 양쪽의 소켓을 같은 행선지 주소 및 포토에 접속하려고 하면, 2개의 접속 소켓이 작성됩니다.이 소켓의 튜플은 완전히 동일합니다.적어도 TCP 접속에서는 동작하지 않습니다(UDP 접속은 실제 접속이 아닙니다).2개의 접속 중 어느 쪽인가에 대해서 데이터가 착신했을 경우, 시스템은 데이터가 어느 접속에 속해 있는지를 판별할 수 없었습니다.적어도 어느 쪽의 접속에 대해서 행선지 주소 또는 행선지 포토가 다른 것이어야, 시스템이 착신 데이터가 어느 접속에 속하는지를 식별하는 문제가 없습니다.

따라서, 같은 프로토콜의 2개의 소켓을 같은 송신원주소와 포토에 바인드 해, 양쪽 모두를 같은 행선지 주소와 포토에 접속하려고 하면,connect()에러와 함께 실제로 실패한다.EADDRINUSE접속하려고 하는 두 번째 소켓의 경우, 즉 5개의 값이 동일한 태플을 가진 소켓이 이미 연결되어 있는 것을 의미합니다.

멀티캐스트 어드레스

대부분의 사람들은 멀티캐스트주소가 존재하지만 존재한다는 사실을 무시합니다.유니캐스트 주소는 일대일 통신에 사용되는 반면 멀티캐스트주소는 일대다 통신에 사용됩니다.대부분의 사람들은 IPv6에 대해 알게 되었을 때 멀티캐스트주소를 알게 되었습니다만, 퍼블릭인터넷에서는 널리 사용되고 있지 않지만 IPv4에도 멀티캐스트주소가 존재했습니다.

의 의미SO_REUSEADDR멀티 캐스트 주소의 변경은, 복수의 소켓을 송신원멀티캐스트주소와 포토의 완전히 같은 편성에 바인드 할 수 있기 때문입니다.즉, 멀티캐스트주소의 경우SO_REUSEADDR와 똑같이 행동하다SO_REUSEPORT를 참조해 주세요.사실, 그 암호는SO_REUSEADDR그리고.SO_REUSEPORT멀티 캐스트 주소의 경우와 같기 때문에, 다음과 같이 말할 수 있습니다.SO_REUSEADDR암시하다SO_REUSEPORT모든 멀티캐스트주소에 대해서, 그 반대도 마찬가지입니다.


FreeBSD/OpenBSD/NetBSD

이 모든 것은 원래 BSD 코드의 레이트 포크이기 때문에 세 가지 모두 BSD와 같은 옵션을 제공하고 BSD와 같은 동작도 합니다.


MacOS(MacOS X)

기본적으로 macOS는 BSD 코드(BSD 4.3)의 다소 늦은 포크(fork)에 기반한 "Darwin"이라는 이름의 BSD 스타일 UNIX이며, 그 후 (당시) FreeB와 다시 동기화되었습니다.Mac OS 10.3 릴리즈용 SD 5 코드 베이스.이것에 의해, Apple은 완전한 POSIX 컴플리언스를 취득할 수 있습니다(macOS는 POSIX 인증 취득).핵심에 마이크로커널("Mach")이 있지만 나머지 커널("XNU")은 기본적으로 BSD 커널에 불과하며, 이것이 macOS가 BSD와 동일한 옵션을 제공하고 BSD와 동일하게 동작하는 이유입니다.

iOS/워치OS/tvOS

iOS는 약간 수정되고 다듬어진 커널, 약간 벗겨진 사용자 공간 도구 세트 및 약간 다른 기본 프레임워크 세트를 가진 macOS 포크일 뿐입니다. watchOS와 tvOS는 iOS 포크이며, 더 나아가서는 watchOS(특히 watchOS)를 제거합니다.제가 아는 바로는 모두 macOS와 똑같이 동작합니다.


리눅스

Linux < 3 . 9

Linux 3.9 이전 버전에서는 옵션만 사용 가능SO_REUSEADDR존재했다.이 옵션은 일반적으로 BSD와 동일하게 동작하지만 다음 두 가지 중요한 예외가 있습니다.

  1. 리스닝(서버) TCP 소켓이 특정 포트에 바인드되어 있는 한,SO_REUSEADDR옵션은 해당 포트를 대상으로 하는 모든 소켓에 대해 완전히 무시됩니다.두 번째 소켓을 같은 포트에 바인드하는 것은 BSD에서도 가능했을 경우에만 가능합니다.SO_REUSEADDR예를 들어 와일드카드 주소로 바인드한 후 보다 구체적인 주소로 바인드하거나 반대로 바인드할 수 없습니다.둘 다 BSD에서 가능합니다.SO_REUSEADDR같은 포트와 2개의 다른 비와일드카드주소에 바인드 할 수 있습니다.이는 항상 허용됩니다.이 점에서는 Linux가 BSD보다 더 제한적입니다.

  2. 두 번째 예외는 클라이언트소켓의 경우 이 옵션은 다음과 같이 동작합니다.SO_REUSEPORTBSD에서는, 양쪽 모두 바인드 되기 전에 이 플래그가 설정되어 있는 한.여러 소켓을 다양한 프로토콜을 위해 동일한 UDP 소켓 주소로 정확하게 바인드할 수 있는 것이 중요하기 때문에 허용한 이유는 다음과 같습니다.SO_REUSEPORT3.9 이전 버전에서는SO_REUSEADDR그 공백을 메우기 위해 적절히 변경되었다.그런 점에서 Linux는 BSD보다 덜 제한적이다.

Linux > = 3.9

Linux 3.9에 옵션이 추가되었습니다.SO_REUSEPORTLinux에도 대응합니다.이 옵션은 BSD의 옵션과 동일하게 동작하며 바인딩 전에 모든 소켓에 이 옵션이 설정되어 있는 한 동일한 주소 및 포트 번호로 바인딩할 수 있습니다.

하지만, 여전히 두 가지 차이점이 있습니다.SO_REUSEPORT기타 시스템:

  1. "포트 하이잭"을 방지하기 위해 다음 한 가지 특별한 제한이 있습니다.동일한 주소와 포트 조합을 공유하는 모든 소켓은 동일한 유효한 사용자 ID를 공유하는 프로세스에 속해야 합니다.따라서 한 사용자가 다른 사용자의 포트를 "도용"할 수 없습니다.이것은 잃어버린 것을 어느 정도 보상하기 위한 특별한 마술이다.SO_EXCLBIND/SO_EXCLUSIVEADDRUSE플래그를 설정합니다.

  2. 또한 커널은 다음과 같은 "특수 마법"을 수행합니다.SO_REUSEPORT다른 운영 체제에는 없는 소켓:UDP 소켓에서는 데이터그램을 균등하게 전달하려고 합니다.TCP 리스닝 소켓에서는 착신 접속 요구(콜에 의해 받아들여진 요구)를 전달하려고 합니다.accept())는, 같은 주소와 포토의 편성을 공유하는 모든 소켓에 균등하게 배치됩니다.따라서 어플리케이션은 여러 하위 프로세스에서 동일한 포트를 쉽게 열고SO_REUSEPORT매우 저렴한 로드 밸런싱을 얻을 수 있습니다.


안드로이드

전체 Android 시스템은 대부분의 Linux 디스트리뷰션과 다소 다르지만, 그 핵심은 약간 수정된 Linux 커널을 사용하기 때문에 Linux에 적용되는 모든 것은 Android에도 적용됩니다.


창문들

Windows 에서는,SO_REUSEADDR옵션, 없습니다.SO_REUSEPORT설정SO_REUSEADDRWindows 의 소켓에서는, 설정과 같이 동작합니다.SO_REUSEPORT그리고.SO_REUSEADDRBSD의 소켓에 접속할 수 있습니다(단, 1개의 예외는 있습니다).

Windows 2003 이전 버전에서는SO_REUSEADDR는, 바인드시에 다른 소켓에 이 옵션이 설정되어 있지 않은 경우에서도, 이미 바인드 된 소켓과 같은 송신원주소와 포토에 항상 바인드 할 수 있었습니다.이 동작에 의해, 애플리케이션은 다른 애플리케이션의 접속 포토를 「도용」할 수 있게 되었습니다.이것이 보안에 큰 영향을 미치는 것은 말할 필요도 없습니다.

마이크로소프트는 이를 깨닫고 또 다른 중요한 소켓 옵션을 추가했습니다.SO_EXCLUSIVEADDRUSE설정SO_EXCLUSIVEADDRUSE바인딩이 성공했을 경우, 송신원주소와 포토의 편성이 이 소켓에 의해서 배타적으로 소유되어 다른 소켓이 바인드 할 수 없는 것을 확인합니다.SO_REUSEADDR세트.

이 디폴트 동작은 Windows 2003에서 처음 변경되었습니다.Microsoft 에서는, 「확장 소켓 시큐러티」(기타 주요 operating system의 디폴트 동작의 재미있는 이름)라고 부릅니다.상세한 것에 대하여는, 이 페이지를 참조해 주세요.테이블이 3개 있습니다.첫 번째 것은 고전적인 동작(호환 모드를 사용하는 경우 아직 사용 중!)을 나타내고 두 번째 것은 Windows 2003 이후의 동작을 나타내고 있습니다.bind()콜은 같은 사용자에 의해 발신되며, 세 번째 콜은 콜이 발신될 때bind()콜은, 다른 유저에 의해서 행해집니다.


솔라리스

Solaris는 SunOS의 후속 모델입니다.SunOS는 원래 BSD의 포크, SunOS 5 이후 SVR4의 포크를 기반으로 했지만 SVR4는 BSD, System V 및 Xenix의 결합이기 때문에 Solaris도 어느 정도까지는 BSD 포크이며 다소 초기 버전입니다.그 결과 Solaris만 알 수 있습니다.SO_REUSEADDR,거기에는 없다SO_REUSEPORT.그SO_REUSEADDRBSD와 거의 동일하게 동작합니다.내가 아는 한 같은 행동을 할 수 있는 방법은 없다.SO_REUSEPORT즉, 2개의 소켓을 동일한 주소와 포트에 바인드할 수 없습니다.

Windows와 마찬가지로 Solaris에는 소켓에 배타적인 바인딩을 부여하는 옵션이 있습니다.이 옵션의 이름은SO_EXCLBIND이 옵션이 바인딩 전에 소켓에 설정되어 있는 경우,SO_REUSEADDR2개의 소켓이 주소 경합으로 테스트되어도 다른 소켓에서는 효과가 없습니다.예:socketA와일드카드 주소에 바인드 되어 있습니다.socketB가지다SO_REUSEADDR이네이블로 되어 있으며, 비패킷 주소 및 와 같은 포트에 바인드되어 있습니다.socketA이 바인딩은 보통 성공합니다.단,socketA가졌다SO_EXCLBIND활성화 되어 있습니다.이 경우, 이 경우, 에러에 관계없이,SO_REUSEADDR의 깃발.socketB.


기타 시스템

사용하시는 시스템이 상기 목록에 없는 경우, 이 두 가지 옵션을 어떻게 처리하는지 알아내기 위해 사용할 수 있는 간단한 테스트 프로그램을 작성했습니다., 제 결과가 잘못되었다고 생각되는 경우는, 코멘트를 투고하거나 잘못된 클레임을 걸기 전에, 그 프로그램을 실행해 주세요.

코드 구축에 필요한 것은 약간의 POSIX API(네트워크 부품용)와 C99 컴파일러(실제로 대부분의 비 C99 컴파일러는 C99 컴파일러가 제공하는 한 동작합니다)뿐입니다.inttypes.h그리고.stdbool.h(예:gccC99의 완전한 지원이 제공되기 훨씬 전에 양쪽이 지원되었습니다).

프로그램이 실행할 필요가 있는 것은 시스템 내의 적어도1개의 인터페이스(로컬인터페이스 이외)에 IP 주소가 할당되어 있고, 그 인터페이스를 사용하는 디폴트루트가 설정되어 있는 것 뿐입니다.프로그램은 이 IP 주소를 수집하여 두 번째 "특정 주소"로 사용합니다.

생각할 수 있는 모든 조합을 테스트합니다.

  • TCP 및 UDP 프로토콜
  • 일반 소켓, 리슨(서버) 소켓, 멀티캐스트 소켓
  • SO_REUSEADDRsocket1, socket2 또는 양쪽 소켓으로 설정
  • SO_REUSEPORTsocket1, socket2 또는 양쪽 소켓으로 설정
  • 사용할 수 있는 모든 주소 조합0.0.0.0(표준),127.0.0.1(특정 주소) 및 프라이머리 인터페이스에서 검출된두 번째 특정 주소(멀티캐스트의 경우,224.1.2.3모든 테스트에서)

좋은 표에 결과를 출력합니다.또, 모르는 시스템에서도 동작합니다.SO_REUSEPORT이 경우 이 옵션은 테스트되지 않습니다.

프로그램이 쉽게 테스트할 수 없는 것은SO_REUSEADDR의 소켓으로 동작합니다.TIME_WAIT이 상태에서 소켓을 강제로 유지하고 유지하는 것은 매우 까다롭기 때문입니다.다행히 대부분의 운영체제는 단순히 BSD처럼 동작하고 대부분의 경우 프로그래머는 단순히 BSD의 존재를 무시할 수 있습니다.

여기 코드가 있습니다(여기에는 포함할 수 없습니다.답변에는 사이즈 제한이 있으며, 이 코드는 이 회신을 제한 이상으로 합니다).

Mecki의 답변은 전적으로 완벽하지만 FreeBSD는 또한SO_REUSEPORT_LBLinux를 모방한SO_REUSEPORT동작 - 부하가 분산됩니다. "setsockopt (2)" 참조

언급URL : https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ

반응형