You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在System.Net.Sockets中实现WSARecv的MSG_PUSH_IMMEDIATE即时接收功能?

Great question! The .NET Socket class doesn’t expose the MSG_PUSH_IMMEDIATE Winsock2 flag directly as a public API, but you absolutely can replicate the same functionality to ignore the PSH flag and forward buffer data immediately. Here are two reliable approaches:

Approach 1: Call WSARecv Directly via PInvoke

Since the .NET Socket wraps a native Winsock socket, you can use its Handle property to access the underlying socket descriptor and call WSARecv directly with the MSG_PUSH_IMMEDIATE flag. This matches your original Winsock2 workflow exactly.

Here’s a simplified implementation:

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

public class ImmediateSocketReceiver
{
    // Define the MSG_PUSH_IMMEDIATE flag (matches Winsock2's value)
    private const int MSG_PUSH_IMMEDIATE = 0x20000;
    private const int SOCKET_ERROR = -1;

    [StructLayout(LayoutKind.Sequential)]
    private struct WSABUF
    {
        public int len;
        public IntPtr buf;
    }

    [DllImport("ws2_32.dll", SetLastError = true)]
    private static extern int WSARecv(
        IntPtr socketHandle,
        [In, Out] WSABUF[] buffers,
        int bufferCount,
        out int bytesReceived,
        ref int flags,
        IntPtr overlapped,
        IntPtr completionRoutine);

    public int ReceiveImmediate(Socket socket, byte[] buffer, int offset, int size)
    {
        if (socket == null || buffer == null)
            throw new ArgumentNullException();
        if (offset < 0 || size < 0 || offset + size > buffer.Length)
            throw new ArgumentOutOfRangeException();

        // Wrap the input buffer in a WSABUF
        var wsabuf = new WSABUF
        {
            len = size,
            buf = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)
        };

        int flags = MSG_PUSH_IMMEDIATE;
        int bytesReceived;

        // Call the native WSARecv function
        int result = WSARecv(socket.Handle, new[] { wsabuf }, 1, out bytesReceived, ref flags, IntPtr.Zero, IntPtr.Zero);
        
        if (result == SOCKET_ERROR)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new SocketException(errorCode);
        }

        return bytesReceived;
    }
}

Approach 2: Use Socket.ReceiveAsync with a Custom SocketFlag

The .NET SocketFlags enum doesn’t include MSG_PUSH_IMMEDIATE, but it’s just a wrapper around integer values. You can cast the flag’s integer value directly to SocketFlags and pass it to asynchronous receive methods like ReceiveAsync. This fits better with .NET’s async programming model.

Example code for async usage:

using System;
using System.Net.Sockets;
using System.Threading.Tasks;

public async Task<int> ReceiveImmediateAsync(Socket socket, byte[] buffer, int offset, int size)
{
    const int MSG_PUSH_IMMEDIATE = 0x20000;
    var args = new SocketAsyncEventArgs();
    args.SetBuffer(buffer, offset, size);
    // Cast the flag value to SocketFlags
    args.SocketFlags = (SocketFlags)MSG_PUSH_IMMEDIATE;

    // Wrap the async operation in a Task
    await Task.Factory.FromAsync(
        callback => socket.ReceiveAsync(args),
        ar => args.BytesTransferred,
        null);

    return args.BytesTransferred;
}

Key Notes

  • Both approaches achieve the same goal: forcing immediate reception of buffer data regardless of the PSH flag, which is critical for low-latency requirements.
  • Choose the PInvoke method if you need synchronous, direct control over the Winsock call. Use the ReceiveAsync approach for a more idiomatic .NET async workflow.

内容的提问来源于stack exchange,提问作者musli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 14:17:36