Как использовать BufferList с SocketAsyncEventArgs и не получить SocketError InvalidArgument?

Я могу использовать SetBuffer с SocketAsyncEventArgs просто отлично.

Если я пытаюсь использовать BufferList (после выполнения SetBuffer(null, 0, 0)), я всегда и сразу получаю SocketError InvalidArgument (10022), когда я выполняю SendAsync на сокете.

Нет НИКАКИХ примеров или документации о том, как использовать BufferList, и что я делаю, имеет смысл (для меня в любом случае).

Может кто-нибудь указать пример программы или фрагмент кода?

Я рву на себе волосы и от меня мало что осталось...

Вот в основном то, что я делаю (например, SocketAsyncEventArgs и lSocket - тот же сокет, который я использую для SetBuffer, который работает)

// null the buffer since we will use a buffer list
e.SetBuffer(null, 0, 0);

// create a bufferlist
e.BufferList = new List<ArraySegment<byte>>();

// create the bufferlist with the network header and the response bytes
e.BufferList.Add(new ArraySegment<byte>(lTxBytes)); // add the 4 character total length
e.BufferList.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lTx.Identity))); // echo back the incoming sequence number
e.BufferList.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lResponse)));

// *** the SendAsync always completes IMMEDIATELY (returns false) gets SocketError InvalidArgument (10022)

if (lSocket.SendAsync(e) == false)
{
      // data was already sent back to the client.
      AppSupport.WriteLog(LogLevel.Flow, "ProcessReceive had SendAsync complete synchronously (bytes transferred {0}).", e.BytesTransferred);
      ProcessSend(e);
}

1 ответ

Решение

Причина, по которой вы получаете исключение, заключается в том, что под капотом SocketAsyncEventArgs использует только буферы, присутствующие в списке во время установки BufferList имущество. В основном вы пытаетесь отправить пустой буфер с кодом:

e.BufferList = new List<ArraySegment<byte>>();   
e.BufferList.Add(new ArraySegment<byte>(lTxBytes));
e.BufferList.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lTx.Identity)));
e.BufferList.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lResponse)));

Вместо этого попробуйте сделать:

var list = new List<ArraySegment<byte>>();
list.Add(new ArraySegment<byte>(lTxBytes));
list.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lTx.Identity)));
list.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lResponse)));
e.BufferList = list;

Это поведение не совсем хорошо документировано и может быть понято только при взгляде на BufferList код установщика в деталях. За кулисами SocketAsyncEventArgs имеет WSABuffer поле массива (для взаимодействия с собственным кодом), где оно копирует и прикрепляет ссылки на массивы байтов при установке BufferList, Так как это WSABuffer[] это отправляется в собственный код, который объясняет, почему ваш код вызывает исключение.

Другие вопросы по тегам