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


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

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

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

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

Я рву на себе волосы из-за этого, и у меня не так много левый...

Вот в основном то, что я делаю (e-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 7

1 ответ:

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

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[] передается в машинный код, это объясняет, почему ваш код создает исключение.