Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

.NET 5부터 지원하는 GetRawSocketOption 사용 시 주의할 점

대개의 경우, 사용이 편리하기 때문에 GetRawSocketOption보다는 GetSocketOption을 사용하게 될 것입니다. 예를 들어, KeepAlive 상태 값을 구하는 경우 이렇게 코딩할 수 있습니다.

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive)); // TcpKeepAliveInterval, TcpKeepAliveTime
return;

// 출력 결과: 0

그런데, .NET 5부터 지원하는 GetRawSocketOption 메서드는,

Socket.GetRawSocketOption(Int32, Int32, Span<Byte>) Method
; https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.getrawsocketoption

인자에 SocketOptionLevel, SocketOptionName enum 타입을 받지 않고 직접 int 값을 전달해야 합니다. 가령 위에서 KeepAlive를 구하기 위해 전달한 SocketOptionLevel.Socket, SocketOptionName.KeepAlive에 대해 각각 상숫값 그대로 다음과 같이 바꿔 코딩할 수 있는데요,

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

byte[] buffer = new byte[4];
// SocketOptionLevel.Socket == 0xffff
// SocketOptionName.KeepAlive == 8
int nbytes = socket.GetRawSocketOption(0xffff, 8, buffer);
int keepAlive = BitConverter.ToInt32(buffer, 0);
Console.WriteLine($"SO_KEEPALIVE: {keepAlive}");

/* 출력 결과
0
SO_KEEPALIVE: 0
*/

문제는, 이 값이 플랫폼별로 다르다는 점입니다. 그래서 위의 소스 코드로 WSL 환경에서 실행하면 이런 예외가 발생합니다.

Unhandled exception. System.Net.Sockets.SocketException (95): Operation not supported
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, Boolean disconnectOnFailure, String callerName)
   at System.Net.Sockets.Socket.GetRawSocketOption(Int32 optionLevel, Int32 optionName, Span`1 optionValue)
   at ConsoleApp1.Program.Main(String[] args) in C:\temp\ConsoleApp1\ConsoleApp1\Program.cs:line 45

따라서, 이 소스 코드를 정상적으로 동작하게 만들려면 SOL_SOCKET == 1, SO_KEEPALIVE == 9로 설정해서,

/*
sys/socket.h

#define SOL_SOCKET	1
#define SO_KEEPALIVE	9
*/

int nbytes = socket.GetRawSocketOption(1, 9, buffer);

실행해야 합니다. 그렇기 때문에 GetSocketOption에서 지원되는 옵션이라면 가능한 그것을 사용하고, 만약 지원되지 않아 GetRawSocketOption을 사용한다면 다중 플랫폼 지원에 따른 고려를 해야 합니다.

제 생각에는, 대충 이런 식으로 코딩을 하는 것이 좋겠습니다. ^^

using System.Net.Sockets;
using System.Runtime.InteropServices;

internal class Program
{
    public static int SOL_SOCKET
    {
        get
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return 0xffff;
            }

            return 1;
        }
    }

    public static int SO_KEEPALIVE
    {
        get
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return 8;
            }

            return 9;
        }
    }            

    static void Main(string[] args)
    {
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Console.WriteLine(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive));
        }

        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            byte[] buffer = new byte[4];
            socket.GetRawSocketOption(SOL_SOCKET, SO_KEEPALIVE, buffer);
            int keepAlive = BitConverter.ToInt32(buffer, 0);
            Console.WriteLine($"SO_KEEPALIVE: {keepAlive}");
        }
    }
}

아쉽군요, 왜 플랫폼마다 다르게 저 상숫값들이 정해졌을까요? ^^;




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 1/23/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 16  [17]  18  19  20  21  22  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13221정성태1/19/20234524Linux: 57. C# - 리눅스 프로세스 메모리 정보파일 다운로드1
13220정성태1/19/20234627오류 유형: 837. NETSDK1045 The current .NET SDK does not support targeting .NET ...
13219정성태1/18/20234234Windows: 220. 네트워크의 인터넷 접속 가능 여부에 대한 판단 기준
13218정성태1/17/20234129VS.NET IDE: 178. Visual Studio 17.5 (Preview 2) - 포트 터널링을 이용한 웹 응용 프로그램의 외부 접근 허용
13217정성태1/13/20234751디버깅 기술: 185. windbg - 64비트 운영체제에서 작업 관리자로 뜬 32비트 프로세스의 덤프를 sos로 디버깅하는 방법
13216정성태1/12/20234981디버깅 기술: 184. windbg - 32비트 프로세스의 메모리 덤프인 경우 !peb 명령어로 나타나지 않는 환경 변수
13215정성태1/11/20236693Linux: 56. 리눅스 - /proc/pid/stat 정보를 이용해 프로세스의 CPU 사용량 구하는 방법 [1]
13214정성태1/10/20236080.NET Framework: 2087. .NET 6부터 SourceGenerator와 통합된 System.Text.Json [1]파일 다운로드1
13213정성태1/9/20235527오류 유형: 836. docker 이미지 빌드 시 "RUN apt install ..." 명령어가 실패하는 이유
13212정성태1/8/20235405기타: 85. 단정도/배정도 부동 소수점의 정밀도(Precision)에 따른 형변환 손실
13211정성태1/6/20235378웹: 42. (https가 아닌) http 다운로드를 막는 웹 브라우저
13210정성태1/5/20234517Windows: 219. 윈도우 x64의 경우 0x00000000`7ffe0000 아래의 주소는 왜 사용하지 않을까요?
13209정성태1/4/20234422Windows: 218. 왜 윈도우에서 가상 메모리 공간은 64KB 정렬이 된 걸까요?
13208정성태1/3/20234392.NET Framework: 2086. C# - Windows 운영체제의 2MB Large 페이지 크기 할당 방법파일 다운로드1
13207정성태12/26/20224660.NET Framework: 2085. C# - gpedit.msc의 "User Rights Assignment" 특권을 코드로 설정/해제하는 방법파일 다운로드1
13206정성태12/24/20224911.NET Framework: 2084. C# - GetTokenInformation으로 사용자 SID(Security identifiers) 구하는 방법 [3]파일 다운로드1
13205정성태12/24/20225162.NET Framework: 2083. C# - C++과의 연동을 위한 구조체의 fixed 배열 필드 사용 (2)파일 다운로드1
13204정성태12/22/20224563.NET Framework: 2082. C# - (LSA_UNICODE_STRING 예제로) CustomMarshaler 사용법파일 다운로드1
13203정성태12/22/20224749.NET Framework: 2081. C# Interop 예제 - (LSA_UNICODE_STRING 예제로) 구조체를 C++에 전달하는 방법파일 다운로드1
13202정성태12/21/20225108기타: 84. 직렬화로 설명하는 Little/Big Endian파일 다운로드1
13201정성태12/20/20225696오류 유형: 835. PyCharm 사용 시 C 드라이브 용량 부족
13200정성태12/19/20224614오류 유형: 834. 이벤트 로그 - SSL Certificate Settings created by an admin process for endpoint
13199정성태12/19/20224820개발 환경 구성: 656. Internal Network 유형의 스위치로 공유한 Hyper-V의 VM과 호스트가 통신이 안 되는 경우
13198정성태12/18/20224761.NET Framework: 2080. C# - Microsoft.XmlSerializer.Generator 처리 없이 XmlSerializer 생성자를 예외 없이 사용하고 싶다면?파일 다운로드1
13197정성태12/17/20224561.NET Framework: 2079. .NET Core/5+ 환경에서 XmlSerializer 사용 시 System.IO.FileNotFoundException 예외 발생하는 경우파일 다운로드1
13196정성태12/16/20224780.NET Framework: 2078. .NET Core/5+를 위한 SGen(Microsoft.XmlSerializer.Generator) 사용법
... 16  [17]  18  19  20  21  22  23  24  25  26  27  28  29  30  ...