重叠Socket.BeginSend / EndSend调用的可预测行为

时间:2014-01-22 13:16:17

标签: c# .net sockets

说,我有一个类,包装一个Socket和(除了其他东西)执行异步数据发送。

我按以下方式执行发送(大大缩写 - 没有错误处理等):

private Socket _socket;

public void Write(byte[] data, Action callback)
{
    _socket.BeginSend(
        data, 0, data.Length, SocketFlags.None,
        new AsyncCallback(WriteMaybeDone),
        new { Data = data, SentSoFar = 0, Callback = callback}
    )
}

public void WriteMaybeDone(IAsyncResult ar)
{
    int bytesSent = _socket.EndSend(ar);
    var state = ar.AsyncState;
    state.SentSoFar += bytesSent;
    if (state.SentSoFar < state.Data.Length) {
        _socket.BeginSend(
            data, state.SentSoFar, State.Data.Length - state.SentSoFar,
            SocketFlags.None,
            new AsyncCallback(WriteMaybeDone), state
        );
    } else {
        if (state.Callback != null) {
            state.Callback();
        }
    }
}

这里我们确保在调用传递的回调之前发送所有数据。

如何确保对Write的“重叠”调用以可预测的方式运行?特别是因为可以在发送所有数据之前调用传递给BeginSend的回调。我需要确保传递给Write的调用的数据转到与数据交错的的数据,然后传递给后续的Write调用,这些调用是在第一次调用之前进行的。写入被解雇。

我受限于.NET 3.5

1 个答案:

答案 0 :(得分:1)

仅在上一次完成后启动下一个发送操作。您可以将要发送的数据入队,或使用信令机制(如AsyncSemaphoreTaskCompletionSource)通知下一次写入前一个已完成。

换句话说,使用生产者 - 消费者设计模式。生产者是想要写作的操作。单个使用者是一个线程或异步工作流,它一个接一个地进行物理写入。