1

我一直在寻找如何增加 UDP 缓冲区,但没有解决方案。

我有某种通过 UDP JPEG 图像发送的网络摄像头。这些由 1024 字节的数据报包中的 cam(无 MTU 分段)划分。当图像大小接近 65K 时,图像会因为丢包而出错。我认为这是因为 UDP 传输提供程序的最大消息大小为 65527(0xfff7),您可以在 Windows SDK 中使用 SpOrder.exe 看到。

我尝试使用“Ws2_32.dll”中的函数 WSCUpdateProvider 更改此大小。我调用 WSCEnumProtocols 来获取 UDP 传输提供程序信息和 WSCGetProviderPath 因为它也是必需的,并且我得到了我需要的信息,但是当我使用管理权限调用 WSCUpdateProvider(无论给出什么信息)时,我总是得到错误:11003 (WSANO_RECOVERY )。

有什么我错过的技巧吗?我没有权利调用这个函数吗?我是否必须编写自己的 UDP 传输提供程序,或者是否有其他解决方案?

这是我在 C# 中的代码:

private void ConfigUDP(uint p)
    {
        Int32 protocol = 17;
        WSAPROTOCOL_INFO[] info = null;
        UInt32 len = 0;
        Int32 err = 0;
        NativeMethods.WSCEnumProtocols(ref protocol, info, ref len, ref err);
        info = new WSAPROTOCOL_INFO[len/Marshal.SizeOf(typeof(WSAPROTOCOL_INFO))];
        Int32 ret = NativeMethods.WSCEnumProtocols(ref protocol, info, ref len, ref err);
        for (int i = 0; i < ret; i++)
        {
            if (info[i].iProtocol != 17)
            {
                continue;
            }
            Int32 pLen = 255;
            StringBuilder path = new StringBuilder(pLen);
            NativeMethods.WSCGetProviderPath(ref info[i].ProviderId, path, ref pLen, ref err);
            WSAPROTOCOL_INFO[] newInfo = new WSAPROTOCOL_INFO[1];
            Array.Copy(info, i, newInfo, 0, 1);
            //newInfo[0].dwMessageSize = (UInt32) p;
            int rs = NativeMethods.WSCUpdateProvider(ref info[i].ProviderId, ref path, newInfo, 1, ref err);
            Console.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).Message);
            Console.WriteLine(new Win32Exception(err).Message);
        }
        ret = NativeMethods.WSCEnumProtocols(ref protocol, info, ref len, ref err);
        for (int i = 0; i < ret; i++)
        {
            Console.WriteLine(info[i].dwMessageSize);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct WSAPROTOCOLCHAIN
    {
        public Int32 ChainLen;                                                                  /* the length of the chain,     */
                                                                                                /* length = 0 means layered protocol, */
                                                                                                /* length = 1 means base protocol, */
                                                                                                /* length > 1 means protocol chain */
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U4, SizeConst = 7)]   /* a list of dwCatalogEntryIds */
        public UInt32[] ChainEntries;
    }

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
    public struct WSAPROTOCOL_INFO
    {
        public UInt32 dwServiceFlags1;
        public UInt32 dwServiceFlags2;
        public UInt32 dwServiceFlags3;
        public UInt32 dwServiceFlags4;
        public UInt32 dwProviderFlags;
        public Guid ProviderId;
        public UInt32 dwCatalogEntryId;
        public WSAPROTOCOLCHAIN ProtocolChain;
        public Int32 iVersion;
        public Int32 iAddressFamily;
        public Int32 iMaxSockAddr;
        public Int32 iMinSockAddr;
        public Int32 iSocketType;
        public Int32 iProtocol;
        public Int32 iProtocolMaxOffset;
        public Int32 iNetworkByteOrder;
        public Int32 iSecurityScheme;
        public UInt32 dwMessageSize;
        public UInt32 dwProviderReserved;
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string szProtocol;
    }

    internal class NativeMethods
    {
        [DllImport("Ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern Int32 WSCUpdateProvider(ref Guid lpProviderId, ref StringBuilder lpszProviderDllPath, WSAPROTOCOL_INFO[] lpProtocolInfoList, UInt32 dwNumberOfEntries, ref Int32 lpErrno);

        [DllImport("Ws2_32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        internal static extern Int32 WSCEnumProtocols(ref Int32 lpiProtocols, [Out] WSAPROTOCOL_INFO[] lpProtocolBuffer, ref UInt32 lpdwBufferLength, ref Int32 lpErrno);

        //Overloaded so I can pass null for iProtocols
        [DllImport("Ws2_32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        internal static extern Int32 WSCEnumProtocols(IntPtr lpiProtocols, [Out] WSAPROTOCOL_INFO[] lpProtocolBuffer, ref UInt32 lpdwBufferLength, ref Int32 lpErrno);

        [DllImport("Ws2_32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        internal static extern Int32 WSCGetProviderPath(ref Guid lpProviderId, [Out] StringBuilder lpszProviderDllPath, ref Int32 lpProviderDllPathLen, ref Int32 lpErrno);
    }
4

0 回答 0