7

I can use SetBuffer with SocketAsyncEventArgs just fine.

If I try to use BufferList (after doing SetBuffer(null, 0, 0)) I always and immediately get SocketError InvalidArgument (10022) when I do SendAsync on the socket.

There are NO examples or documentation on how to use BufferList and what I am doing makes sense (to me anyway).

Can someone point out an example program or code snippet?

I'm tearing my hair out over this and don't have much left ...

Here is basically what I am doing (e is SocketAsyncEventArgs and lSocket is the same socket I use for SetBuffer which works)

// 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);
}
user229044
  • 232,980
  • 40
  • 330
  • 338
Dave
  • 1,822
  • 2
  • 27
  • 36
  • You have a better chance of getting answer for your question if you tag it with the language you use. – Felix Kling Aug 05 '12 at 22:45
  • Do all the ArraySegments need to be part of the same physical byte array? If that is the case, it would render BufferList fairly useless. Has anyone used BufferList successfully? – Dave Aug 07 '12 at 22:34

1 Answers1

12

The reason you are getting an exception is that under the hood the SocketAsyncEventArgs only uses the buffers present in the list at the time of setting the BufferList property. Basically you are trying to send en empty buffer with the code :

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)));

Instead try to do :

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;

This behavior is not well documented at all and can only be understood by looking at the BufferList setter code in detail. Behind the scenes the SocketAsyncEventArgs has a WSABuffer array field(for interop with native code) where it copies and pins the byte arrays references when you set the BufferList. Since it is this WSABuffer[] that is sent to native code, that explains why your code throws an exception.

JJ15k
  • 520
  • 6
  • 12
  • 1
    Definitely not, I was encountering the same issue when I found your post and was very disappointed no one had answered. MS should really document this better. Too bad I am a year late answering you ;). – JJ15k Jul 06 '13 at 12:51