>  기사  >  백엔드 개발  >  소켓에서 so_reuseport와 so_reuseaddr의 차이점을 자세히 논의하세요.

소켓에서 so_reuseport와 so_reuseaddr의 차이점을 자세히 논의하세요.

不言
不言원래의
2018-04-28 15:15:161739검색

다음 기사에서는 소켓에서 so_reuseport와 so_reuseaddr의 차이점에 대해 자세히 논의할 것입니다. 이는 좋은 참고 가치가 있으며 모든 사람에게 도움이 되기를 바랍니다. 함께 살펴볼까요

소켓의 기본 배경

이 두 옵션의 차이점을 논할 때 우리가 알아야 할 것은 BSD 구현이 모든 소켓 구현의 근원이라는 것입니다. 기본적으로 다른 모든 시스템은 어느 정도 BSD 소켓 구현(또는 적어도 해당 인터페이스)을 참조한 후 자체적으로 독립적인 진화를 시작했습니다. 분명히 BSD 자체는 시간이 지남에 따라 끊임없이 진화하고 변화하고 있습니다. 따라서 나중에 BSD를 참조하는 시스템은 이전에 BSD를 참조하는 시스템보다 더 많은 기능을 갖습니다. 따라서 BSD 소켓 구현을 이해하는 것은 다른 소켓 구현을 이해하는 초석입니다. BSD 소켓 구현을 분석해 보겠습니다.

이전에 먼저 TCP/UDP 연결을 고유하게 식별하는 방법을 이해해야 합니다. TCP/UDP는 다음 5개 튜플로 고유하게 식별됩니다.


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


이러한 값의 고유한 조합은 연결을 고유하게 식별합니다. 그러면 어떤 연결에서도 이 다섯 가지 값은 완전히 동일할 수 없습니다. 그렇지 않으면 운영 체제가 이러한 연결을 구별할 수 없습니다.

소켓의 프로토콜은 소켓()으로 초기화될 때 설정됩니다. 소스 주소와 소스 포트는 바인딩()을 호출할 때 설정됩니다. 목적지 주소와 목적지 포트는 connect()를 호출할 때 설정됩니다. UDP는 Connectionless이며, UDP 소켓은 목적지 포트에 연결하지 않고도 사용할 수 있습니다. 그러나 경우에 따라 대상 주소 및 포트와 연결을 설정한 후 UDP를 사용할 수도 있습니다. 비연결형 UDP를 사용하여 데이터를 보낼 때, bind()가 명시적으로 호출되지 않으면 시스템은 처음으로 데이터를 보낼 때 UDP 소켓을 로컬 주소와 특정 포트에 자동으로 바인딩합니다. 원격 호스트). 마찬가지로 바인딩된 주소가 없는 TCP 소켓은 연결이 설정될 때 자동으로 로컬 주소 및 포트에 바인딩됩니다.

수동으로 포트를 바인딩하면 소켓을 포트 0에 바인딩할 수 있습니다. 포트 0에 바인딩한다는 것은 시스템이 사용할 포트를 결정하도록 하는 것을 의미합니다(보통 사전 범위에서 결정된 운영 체제별 포트 번호 집합에서). 그것은 모든 항구를 의미합니다. 마찬가지로 와일드카드를 사용하여 시스템이 바인딩할 소스 주소를 결정하도록 할 수도 있습니다(ipv4 와일드카드는 0.0.0.0, ipv6 와일드카드는::). 포트와 달리 소켓은 호스트의 모든 인터페이스에 해당하는 모든 주소에 바인딩될 수 있습니다. 이 소켓에 연결된 대상 주소와 라우팅 테이블의 해당 정보를 기반으로 운영 체제는 이 소켓을 바인딩할 적절한 주소를 선택하고 이 주소를 사용하여 이전 와일드카드 IP 주소를 대체합니다.

기본적으로 두 개의 소켓은 동일한 소스 주소 및 소스 포트 조합에 바인딩될 수 없습니다. 예를 들어, 소켓A를 주소 A:X에 바인딩하고, 소켓B를 주소 B:Y에 바인딩합니다. 여기서 A와 B는 IP 주소이고 X와 Y는 포트입니다. 그러면 A==B일 때 X!=Y가 충족되어야 하고, X==Y일 때 A!=B가 충족되어야 합니다. 특정 소켓이 와일드카드 IP 주소에 바인딩된 경우 실제로 로컬 시스템의 모든 IP는 시스템에 의해 바인딩된 것으로 간주됩니다. 예를 들어 소켓은 0.0.0.0:21에 바인딩됩니다. 이 경우 어떤 특정 IP 주소를 선택하든 다른 소켓은 더 이상 포트 21에 바인딩될 수 없습니다. 와일드카드 IP0.0.0.0이 모든 로컬 IP와 충돌하기 때문입니다.

위의 모든 사항은 기본적으로 주요 운영 체제에서 동일합니다. 각 SO_REUSEADDR은 서로 다른 의미를 갖습니다. 먼저 BSD 구현에 대해 논의해 보겠습니다. BSD는 다른 모든 소켓 구현 방법의 소스이기 때문입니다.

BSD

SO_REUSEADDR

소켓의 SO_REUSEADDR 속성이 특정 주소 및 포트에 바인딩하기 전에 설정된 경우, 소켓이 정확히 동일한 소스 주소에 다른 소켓에 바인딩을 시도하지 않는 한 그렇지 않으면 소켓이 이 주소 포트 쌍을 성공적으로 바인딩할 수 있습니다. 이전과 똑같이 들릴 수도 있습니다. 그러나 핵심 단어는 완전합니다. SO_REUSEADDR은 주로 시스템이 와일드카드 IP 주소 충돌을 처리하는 방식을 변경합니다.

SO_REUSEADDR을 사용하지 않고 소켓A를 0.0.0.0:21에 바인딩하면 로컬 시스템의 다른 소켓을 포트 21에 바인딩(예: 192.168.1.1:21에 바인딩)하면 EADDRINUSE 오류가 발생합니다. 0.0.0.0은 임의의 IP 주소를 의미하는 와일드카드 IP 주소이므로 이 시스템의 다른 모든 IP 주소는 시스템에서 사용되는 것으로 간주됩니다. SO_REUSEADDR 옵션이 설정된 경우 0.0.0.0:21과 192.168.1.1:21은 정확히 동일한 주소 포트 쌍이 아니기 때문에(그 중 하나는 와일드카드 IP 주소이고 다른 하나는 로컬 머신의 특정 IP 주소) 그러한 바인딩은 확실히 성공할 수 있습니다. SO_REUSEADDR이 설정되어 있는 한 소켓A 및 소켓B가 초기화되는 순서에 관계없이 바인딩은 성공하고 SO_REUSEADDR이 설정되지 않은 한 바인딩은 성공하지 못합니다.

아래 표에는 몇 가지 가능한 시나리오와 그 결과가 나열되어 있습니다.


알았어오류(EADDRINUSE)오류(EADDRINUSE)OK확인 OK
SO_REUSEADDR socketA socketB Result
ON / OFF 192.1 .1:21 192.168.1.1:21 오류(EADDRINUSE) ㅋㅋㅋ 8.1.1 :21
OFF 192.168.1.1:21 0.0.0.0:21
OFF 0.0.0.0:21 192.168.1.1 :2 1
ON 192.168.1.1:21 0.0.0.0:21
ON 0.0.0.0:21 192.168.1.1:21
ON / OFF 0.0.0.0: 21 0.0.0.0: 21

이 표에서는 소켓A가 테이블의 해당 주소에 성공적으로 바인딩된 다음, 소켓B가 초기화되고, SO_REUSEADDR 설정이 표의 첫 번째 열에 표시된 대로 이루어진 다음, 소켓B가 테이블의 해당 주소에 바인딩을 시도한다고 가정합니다. 결과 열은 바인딩의 결과입니다. 첫 번째 열의 값이 ON/OFF인 경우 SO_REUSEADDR 설정 여부는 결과와 관련이 없습니다.

와일드카드 IP 주소에 대한 SO_REUSEADDR의 역할은 위에서 논의되었지만 이 역할만 있는 것은 아닙니다. 또 다른 역할은 서버 측 프로그래밍을 수행할 때 모든 사람이 SO_REUSEADDR 옵션을 사용하는 이유입니다. 다른 역할과 중요한 응용 프로그램을 이해하려면 먼저 TCP 프로토콜이 어떻게 작동하는지 더 깊이 논의해야 합니다.

각 소켓에는 해당 전송 버퍼가 있습니다. send() 메소드가 성공적으로 호출되면 실제로 보내야 하는 데이터가 반드시 즉시 전송될 필요는 없지만 전송 버퍼에 추가됩니다. UDP 소켓의 경우 즉시 전송되지 않더라도 일반적으로 데이터가 빠르게 전송됩니다. 그러나 TCP 소켓의 경우 송신 버퍼에 데이터를 추가한 후 실제로 데이터가 전송되기까지 비교적 오랜 시간이 걸릴 수 있습니다. 따라서 TCP 소켓을 닫을 때 실제로 송신 버퍼에 전송 대기 중인 데이터가 여전히 있을 수 있습니다. 하지만 이때 send()는 성공을 반환하기 때문에 우리 코드에서는 데이터가 실제로 성공적으로 전송되었다고 생각합니다. close()를 호출한 직후에 TCP 소켓이 닫히면 이 모든 데이터가 손실되고 우리 코드는 이에 대해 전혀 알 수 없습니다. 그러나 TCP는 신뢰할 수 있는 전송 계층 프로토콜이므로 전송할 데이터를 직접 삭제하는 것은 분명히 바람직하지 않습니다. 실제로 송신 버퍼에 전송할 데이터가 남아 있는 동안 소켓의 close() 메서드를 호출하면 소위 TIME_WAIT 상태에 진입하게 됩니다. 이 상태에서 소켓은 모든 데이터가 성공적으로 전송되거나 시간 초과가 발생할 때까지 버퍼에 있는 데이터 전송을 계속 시도합니다.

소켓을 강제로 닫기 전 운영 체제 커널의 최대 대기 시간을 링거 시간이라고 합니다. 지연 시간은 대부분의 시스템에서 전체적으로 설정되며 비교적 길다(대부분의 시스템은 2분으로 설정). 소켓을 초기화할 때 SO_LINGER 옵션을 사용하여 각 소켓의 지연 시간을 구체적으로 설정할 수도 있습니다. 지연된 대기를 완전히 끌 수도 있습니다. 그러나 지연 시간을 0으로 설정하는 것(지연 대기를 완전히 끄는 것)은 좋은 프로그래밍 방식이 아니라는 점에 유의해야 합니다. TCP 소켓을 정상적으로 닫는 것은 원격 호스트와 여러 데이터 패킷을 교환(패킷 손실 시 손실 재전송 포함)하는 등 비교적 복잡한 프로세스이고, 이 데이터 패킷 교환 프로세스에 필요한 시간도 지연 시간에 포함되기 때문입니다. . 지연 대기를 비활성화하면 소켓은 닫힐 때 전송할 모든 데이터를 삭제할 뿐만 아니라 항상 강제로 닫힙니다(TCP는 연결 지향 프로토콜이므로 원격 포트와 닫는 패킷을 교환하지 않으면 다음과 같은 결과가 발생합니다). 원격 포트가 오랫동안 대기 중인 상태입니다.) 따라서 일반적으로 실제 프로그래밍에서는 이 작업을 수행하지 않는 것이 좋습니다. TCP 연결 해제 프로세스는 이 기사의 범위를 벗어납니다. 관심이 있는 경우 이 페이지를 참조할 수 있습니다. 그리고 실제로 지연 대기를 비활성화하고 소켓을 명시적으로 닫지 않고 프로그램이 종료되면 BSD(및 다른 시스템)는 우리 설정을 무시하고 지연 대기를 수행합니다. 예를 들어 프로그램이 exit() 메소드를 호출하거나 신호를 사용하여 해당 프로세스가 종료되는 경우(불법적인 메모리 액세스 등으로 인해 프로세스가 중단되는 경우 포함). 따라서 모든 상황에서 지연 대기 시간에 관계없이 소켓이 종료된다고 100% 보장할 수는 없습니다.

여기서 문제는 운영 체제가 TIME_WAIT 단계에서 소켓을 처리하는 방식입니다. SO_REUSEADDR 옵션이 설정되지 않은 경우 TIME_WAIT 단계의 소켓은 여전히 ​​원래 주소 및 포트에 바인딩된 것으로 간주됩니다. 소켓이 완전히 닫힐 때까지(TIME_WAIT 단계 종료) 새 소켓을 이 주소 및 포트 쌍에 바인딩하려는 다른 시도는 성공하지 못합니다. 이 대기 시간은 지연된 대기 시간만큼 길 수 있습니다. 따라서 방금 닫힌 소켓에 해당하는 주소 및 포트 쌍에 새 소켓을 즉시 바인딩할 수 없습니다. 이 작업은 대부분의 경우 실패합니다.

그러나 새 소켓에 SO_REUSEADDR 옵션을 설정하면 현재 주소 포트 쌍에 바인딩된 다른 소켓이 있고 TIME_WAIT 단계에 있으면 이 기존 바인딩 관계는 무시됩니다. 실제로 TIME_WAIT 단계의 소켓은 이미 semi-closed 상태이므로 이 주소와 포트 쌍에 새 소켓을 바인딩하는 데 문제가 없습니다. 이 경우 이 포트에 바인딩된 원래 소켓은 일반적으로 새 소켓에 영향을 주지 않습니다. 그러나 어떤 시점에서는 TIME_WAIT 단계에 있지만 여전히 작동 중인 소켓에 해당하는 주소 포트 쌍에 새 소켓을 바인딩하면 의도하지 않고 예측할 수 없는 부정적인 영향을 미칠 수 있다는 점에 유의해야 합니다. 그러나 이 문제는 이 기사의 범위를 벗어납니다. 다행스럽게도 이러한 부정적인 영향은 실제로 거의 나타나지 않습니다.

마지막으로 SO_REUSEADDR에 대해 주목해야 할 한 가지는 새 소켓에 대해 SO_REUSEADDR을 설정하는 한 위의 모든 내용이 적용된다는 것입니다. 현재 주소와 포트 쌍에 바인딩된 원래 소켓의 경우 TIME_WAIT 단계의 소켓에 SO_REUSEADDR이 설정되어 있는지 여부는 영향을 미치지 않습니다. 바인드 작업의 성공 여부를 결정하는 코드는 단순히 바인드() 메서드에 전달된 새 소켓의 SO_REUSEADDR 옵션을 확인합니다. 관련된 다른 소켓의 SO_REUSEADDR 옵션은 확인되지 않습니다.

SO_REUSEPORT

많은 사람들이 SO_REUSEADDR을 SO_REUSEPORT로 착각합니다. 기본적으로 SO_REUSEPORT를 사용하면 이전에 바인딩된 모든 소켓에 SO_REUSEPORT 옵션이 설정되어 있는 한 원하는 수의 소켓을 정확히 동일한 소스 주소 및 포트 쌍에 바인딩할 수 있습니다. 주소 및 포트 쌍에 바인딩된 첫 번째 소켓에 SO_REUSEPORT가 설정되지 않은 경우 후속 소켓이 SO_REUSEPORT를 설정했는지 여부에 관계없이 이 주소 포트와 정확히 동일한 주소에 바인딩될 수 없습니다. 이 주소와 포트 쌍에 바인딩된 첫 번째 소켓이 바인딩 관계를 해제하지 않는 한. SO_REUSEADDR과 달리 SO_REUSEPORT를 처리하는 코드는 현재 바인딩을 시도하는 소켓의 SO_REUSEPORT를 검사할 뿐만 아니라 현재 바인딩을 시도하는 주소 포트 쌍에 이전에 바인딩된 소켓의 SO_REUSEPORT 옵션도 검사합니다.

SO_REUSEPORT는 SO_REUSEADDR과 동일하지 않습니다. 이것이 의미하는 바는 이미 바인딩된 주소가 있는 소켓에 SO_REUSEPORT가 설정되어 있지 않고 다른 새 소켓에 SO_REUSEPORT가 설정되어 있으며 현재 소켓과 정확히 동일한 포트 주소 쌍에 바인딩하려고 시도하는 경우 바인딩 시도가 실패한다는 것입니다. 동시에 현재 소켓이 이미 TIME_WAIT 단계에 있고 SO_REUSEPORT 옵션이 설정된 새 소켓이 현재 주소에 바인딩을 시도하면 바인딩 작업도 실패합니다. 현재 TIME_WAIT 단계에 있는 소켓에 해당하는 주소 포트 쌍에 새 소켓을 바인딩하려면 바인딩하기 전에 새 소켓의 SO_REUSEADDR 옵션을 설정하거나 바인딩하기 전에 두 소켓 모두에 대해 이를 설정해야 합니다. 옵션. 물론 소켓에 대해 SO_REUSEADDR 및 SO_REUSEPORT 옵션을 동시에 설정하는 것도 가능합니다.

SO_REUSEPORT는 SO_REUSEADDR 이후 BSD 시스템에 추가되었습니다. 이것이 현재 일부 시스템의 소켓 구현에 SO_REUSEPORT 옵션이 없는 이유입니다. 이 옵션이 BSD 시스템에 추가되기 전에 BSD 소켓 구현을 참조했기 때문입니다. 이 옵션이 추가되기 전에는 BSD 시스템에서 두 개의 소켓을 정확히 동일한 주소 및 포트 쌍에 바인딩할 수 있는 방법이 없었습니다.

Connect()는 EADDRINUSE를 반환합니까?

때때로 바인딩() 작업이 EADDRINUSE 오류를 반환합니다. 그러나 이상한 점은 connect() 작업을 호출할 때 EADDRINUSE 오류가 발생할 수도 있다는 것입니다. 왜 이런가요? 현재 포트에서 연결을 설정하려는 원격 주소도 사용되는 이유는 무엇입니까? 동일한 원격 주소에 여러 소켓을 연결할 때 문제가 있습니까?

이 글에서 앞서 언급했듯이 연결 관계는 5배로 결정됩니다. 모든 연결 관계에서 이 5중은 고유해야 합니다. 그렇지 않으면 시스템이 두 연결을 구별할 수 없습니다. 이제 주소 재사용을 사용하면 동일한 프로토콜을 사용하는 두 개의 소켓을 동일한 주소 포트 쌍에 바인딩할 수 있습니다. 이는 이 두 소켓의 경우 5-튜플 {a88b79ba1ccee8890e978c768d80530d, 3037a7cee66f0ae45683db6cc2520e8a, 1b9006debff836a11384f3384ae84936}가 이미 동일하다는 것을 의미합니다. 이 경우 두 연결을 모두 동일한 원격 주소 포트에 연결하려고 하면 두 연결 관계의 5튜플은 정확히 동일합니다. 즉, 두 개의 동일한 연결이 생성됩니다. 이는 TCP 프로토콜에서는 허용되지 않습니다(UDP는 연결이 없음). 두 개의 동일한 연결 중 하나가 데이터를 수신하면 시스템은 해당 데이터가 어느 연결에 속하는지 알 수 없습니다. 따라서 이 경우 최소한 두 소켓이 연결하려는 원격 호스트의 주소와 포트는 동일할 수 없습니다. 이러한 방식으로만 시스템이 이 두 연결 관계를 계속해서 구별할 수 있습니다.

따라서 동일한 프로토콜을 사용하여 두 개의 소켓을 동일한 로컬 주소 및 포트 쌍에 바인딩할 때 두 소켓을 동일한 대상 주소 및 포트 쌍에 연결하려고 하면 두 번째 소켓은 connect() 메서드를 호출하려고 시도합니다. 정확히 동일한 5튜플을 가진 소켓이 이미 존재함을 나타내는 EADDRINUSE 오류를 보고합니다.

멀티캐스트 주소

일대일 통신에 사용되는 유니캐스트 주소에 비해 일대다 통신에는 멀티캐스트 주소가 사용됩니다. IPv4와 IPv6 모두 멀티캐스트 주소를 가지고 있습니다. 그러나 IPv4의 멀티캐스트는 공용 네트워크에서 거의 사용되지 않습니다.

멀티캐스트 주소의 경우 SO_REUSEADDR의 의미가 이전과 달라집니다. 이 경우 SO_REUSEADDR을 사용하면 여러 소켓을 정확히 동일한 소스 브로드캐스트 주소 및 포트 쌍에 바인딩할 수 있습니다. 즉, 멀티캐스트 주소의 경우 SO_REUSEADDR은 유니캐스트 통신의 SO_REUSEPORT와 동일합니다. 실제로 멀티캐스트의 경우 SO_REUSEADDR과 SO_REUSEPORT는 정확히 동일한 효과를 갖습니다.

FreeBSD/OpenBSD/NetBSD

이 모든 시스템은 최신 기본 BSD 시스템 코드를 참조합니다. 따라서 이 세 가지 시스템은 BSD와 정확히 동일한 소켓 옵션을 제공하며 이러한 옵션의 의미는 기본 BSD와 정확히 동일합니다.

MacOS X

MacOS의 핵심 코드 구현도 동일합니다.

iOS

iOS는 실제로 약간 수정된 MacOS X이므로 MacOS X에서 작동하는 것은 iOS에서도 작동합니다.

Linux

Linux3.9 이전에는 SO_REUSEADDR 옵션만 존재했습니다. 이 옵션의 기능은 기본적으로 BSD 시스템과 동일합니다. 그러나 여전히 두 가지 중요한 차이점이 있습니다.

첫 번째 차이점은 수신(서버) 상태의 TCP 소켓이 와일드카드 IP 주소와 특정 포트에 바인딩된 경우 이 두 소켓에 SO_REUSEADDR 옵션이 설정되어 있는지 여부에 관계없이 다른 TCP 소켓이 가능하다는 것입니다. 더 이상 동일한 포트에 바인딩되지 않습니다. 이는 다른 소켓이 특정 IP 주소(BSD 시스템에서 허용되는 대로)를 사용하는 경우에도 작동하지 않습니다. 비수신(클라이언트) TCP 소켓에는 이러한 제한이 없습니다.

두 번째 차이점은 UDP 소켓의 경우 SO_REUSEADDR이 BSD의 SO_REUSEPORT와 동일한 기능을 갖는다는 것입니다. 따라서 두 개의 UDP 소켓에 SO_REUSEADDR이 설정되어 있으면 정확히 동일한 주소 및 포트 쌍 집합에 바인딩될 수 있습니다.

Linux3.9에는 SO_REUSEPORT 옵션이 추가되었습니다. 두 개 이상의 TCP 또는 UDP, 수신(서버) 또는 비수신(클라이언트) 소켓은 포트에서 주소를 바인딩하기 전에 모든 소켓(첫 번째 소켓 포함)에 이 옵션이 설정되어 있는 한 정확히 동일한 주소에 바인딩될 수 있습니다. 콤비네이션. 동시에, 포트 하이재킹을 방지하기 위해 특별한 제한 사항이 있습니다. 동일한 주소 및 포트 조합에 바인딩하려는 모든 소켓은 동일한 사용자 ID를 가진 프로세스에 속해야 합니다. 따라서 한 사용자는 다른 사용자의 포트를 "훔칠" 수 없습니다.

또한 SO_REUSEPORT 옵션이 설정된 소켓의 경우 Linux 커널은 다른 시스템에는 없는 몇 가지 특수 작업도 수행합니다. 동일한 주소 및 포트 조합에 바인딩된 UDP 소켓의 경우 커널은 이들 소켓 간에 연결을 시도합니다. 수신된 데이터 패킷, 동일한 주소 및 포트 조합에 바인딩된 TCP 수신 소켓의 경우 커널은 수신된 연결 요청(accept() 메서드를 호출하여 얻은 요청)을 두 패킷 간에 균등하게 분배하려고 시도합니다. 이는 주소 재사용을 허용하지만 수신된 패킷이나 연결 요청을 동일한 주소 및 포트 조합에 연결된 소켓에 무작위로 할당하는 다른 시스템과 비교하여 Linux는 트래픽 분산을 최적화하려고 시도한다는 것을 의미합니다. 예를 들어, 간단한 서버 프로세스의 여러 다른 인스턴스는 SO_REUSEPORT를 사용하여 간단한 로드 밸런싱을 쉽게 구현할 수 있으며, 커널은 이 로드 밸런싱을 담당하며 이는 프로그램에 완전히 무료입니다!

Android

Android의 핵심 부분은 약간 수정된 Linux 커널이므로 Linux에서 작동하는 모든 것이 Android에서도 작동합니다.

Windows

Windows에는 SO_REUSEADDR 옵션만 있습니다. Windows에서 소켓에 SO_REUSEADDR을 설정하는 것은 BSD에서 동시에 소켓에 ​​SO_REUSEPORT 및 SO_REUSEADDR을 설정하는 것과 동일한 효과를 갖습니다. 그러나 차이점은 바인딩된 주소가 있는 다른 소켓에 SO_REUSEADDR이 설정되지 않은 경우에도 SO_REUSEADDR이 설정된 소켓은 항상 다른 바인딩된 소켓과 정확히 동일한 주소 및 포트 조합에 바인딩될 수 있다는 것입니다. 이런 행동은 다소 위험하다고 할 수 있습니다. 하나의 애플리케이션이 연결된 포트에 대한 다른 참조의 데이터를 훔칠 수 있기 때문입니다. Microsoft는 이 문제를 인식하고 SO_EXCLUSIVEADDRUSE라는 또 다른 소켓 옵션을 추가했습니다. 소켓에 SO_EXCLUSIVEADDRUSE를 설정하면 소켓이 주소 및 포트 조합에 바인딩되면 SO_REUSEADDR 설정 여부에 관계없이 다른 모든 소켓이 더 이상 현재 주소 및 포트 조합에 바인딩될 수 없습니다.

Solaris

Solaris는 SunOS의 후속 제품입니다. SunOS는 어느 정도 이전 버전의 BSD에서 파생된 것이기도 합니다. 따라서 Solaris에서는 SO_REUSEADDR만 제공하며 성능은 기본적으로 BSD 시스템과 동일합니다. 내가 아는 한, SO_REUSEPORT와 동일한 기능은 Solaris 시스템에서 구현할 수 없습니다. 이는 Solaris에서는 두 개의 소켓을 정확히 동일한 주소 및 포트 조합에 바인딩할 수 없음을 의미합니다.

Windows와 마찬가지로 Solaris도 소켓에 대한 독점 바인딩 옵션인 SO_EXCLBIND를 제공합니다. 소켓이 주소를 바인딩하기 전에 이 옵션을 설정하면 다른 소켓은 SO_REUSEADDR이 설정되어 있어도 동일한 주소에 바인딩할 수 없습니다. 예를 들어, 소켓A가 와일드카드 IP 주소에 바인딩되고, 소켓B가 SO_REUSEADDR로 설정되고, 특정 IP 주소와 소켓A와 동일한 포트의 조합에 바인딩된 경우, 소켓A가 SO_EXCLBIND로 설정되지 않으면 이 작업이 성공하고, 그렇지 않으면 성공합니다. 실패하다.

참조:

http://stackoverflow.com/a/14388707/6037083


위 내용은 소켓에서 so_reuseport와 so_reuseaddr의 차이점을 자세히 논의하세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.