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