C# 访问c中给定套接字的TCP重传字节数(和重传数据包数)#

C# 访问c中给定套接字的TCP重传字节数(和重传数据包数)#,c#,.net,sockets,.net-core,tcp,C#,.net,Sockets,.net Core,Tcp,我想将TCPListener/TCPClient与异步回调和IOCP一起用于一些TCP性能软件 我希望能够获得TCP堆栈为当前活动套接字重新传输的字节数 我注意到mstcpip.h具有struct\u TCP\u INFO\u v0。其中包含以下字段: typedef struct _TCP_INFO_v0 { ... ULONG BytesRetrans; ... } MS文档说明: 要获取此结构的实例,请使用SIO\u TCP\u INFO控制代码调用WSAIoctl或L

我想将TCPListener/TCPClient与异步回调和IOCP一起用于一些TCP性能软件

我希望能够获得TCP堆栈为当前活动套接字重新传输的字节数

我注意到mstcpip.h具有struct\u TCP\u INFO\u v0。其中包含以下字段:

typedef struct _TCP_INFO_v0 {
  ...
  ULONG    BytesRetrans;
  ...
}
MS文档说明:

要获取此结构的实例,请使用SIO\u TCP\u INFO控制代码调用WSAIoctlLPWSPIoctl函数

我找不到通过必要的p/invoke调用来钻取.NET对象的方法来获取此信息。有人可以用TCPClient作为起点来帮助编写代码片段吗

谢谢


对于专家来说,获得重新传输的数据包的数量也很好,但是我还没有找到一个变量。我猜数据包组装和跟踪将发生在tcp堆栈之下的某个级别,实际上,两个丢失的连续数据包可以作为单个数据包重新传输,一个丢失的数据包可以作为两个或更多数据包重新传输——尽管我从未在数据包跟踪中看到过这一点——但我一直没有注意到这一点也很难。

使用C.Gonzalez提供的注释,这里有一些代码似乎可以工作。它需要对有损连接进行一些测试,并清理类型和转换

    struct TCP_INFO_v0
    {
        public UInt32 State;
        public UInt32 Mss;
        public UInt64 ConnectionTimeMs;
        public byte TimestampsEnabled;
        public UInt32 RttUs;
        public UInt32 MinRttUs;
        public UInt32 BytesInFlight;
        public UInt32 Cwnd;
        public UInt32 SndWnd;
        public UInt32 RcvWnd;
        public UInt32 RcvBuf;
        public UInt64 BytesOut;
        public UInt64 BytesIn;
        public UInt32 BytesReordered;
        public UInt32 BytesRetrans;
        public UInt32 FastRetrans;
        public UInt32 DupAcksIn;
        public UInt32 TimeoutEpisodes;
        public byte SynRetrans;
    }

    // SIO_TCP_INFO as defined in winsdk-10/mstcpip.h
    readonly static int SIO_TCP_INFO = unchecked((int)0xD8000027);
    static void Main(string[] args)
    {
        TcpClient tcpClient = new TcpClient("127.0.0.1", 445);

        var outputArray = new byte[128];
        tcpClient.Client.IOControl(SIO_TCP_INFO, BitConverter.GetBytes(0), outputArray);

        GCHandle handle = GCHandle.Alloc(outputArray, GCHandleType.Pinned);
        TCP_INFO_v0 tcpInfo = (TCP_INFO_v0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(TCP_INFO_v0));
        handle.Free();

        Console.WriteLine("Bytes retransmitted: {0}", tcpInfo.BytesRetrans);

    }

对于已建立的TcpClient,您应该能够执行
myTcpClient.Client.IOControl(SIO_TCP_INFO,BitConverter.GetBytes(0),outputArray)
,其中SIO_TCP_INFO=-671088583(0xD800039)和
outputArray
是一个大小合适的字节数组(128应该足够了)。outputArray将包含所需的结构,并且可以通过适当的强制转换检索所需的值。IOControl本身将返回输出数组中的相关字节数。@C.Gonzalez不是“(0xD800039)”,而是“(0xD800027)”,因为代码是“\u WSAIORW(IOC\u供应商,39)”。也就是说,39是十进制的,而不是十六进制。@G.Vanem你说得对,错了。