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