How use BufferList with SocketAsyncEventArgs and not get SocketError InvalidArgument?

Answered How use BufferList with SocketAsyncEventArgs and not get SocketError InvalidArgument?

  • Sunday, August 05, 2012 10:28 PM
     
     

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

    Thanks, Dave




All Replies

  • Monday, August 06, 2012 8:59 AM
     
      Has Code

    I your case e is a class and bufferList is a variable inside the class.  You are trying to send the entire class instead of just the buffered data.  I like setting a variable to the list to simplify the syntax

    var databuffer = ((state)e).BufferList[lastindex].ToArray() as byte[];

     if (lSocket.SendAsync(databuffer) == false)

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
            }
            static void mycallback(EventArgs e)
            {
                
                ((state)e).BufferList = new List<List<byte>>();
                int lastindex = ((state)e).BufferList.Count() - 1;
                var databuffer = ((state)e).BufferList[lastindex].ToArray() as byte[];
            }
        }
        public class state : EventArgs 
        {
            public List<List<byte>> BufferList;
        }


    jdweng

  • Monday, August 06, 2012 3:37 PM
     
     
    Thanks but that has nothing to do with using SocketAsyncEventArgs for asynchronous sockets where BufferList must be a "List<ArraySegment<byte>>()" object. Search on SocketAsyncEventArgs and read about BufferList please. It needs byte[] arrays not Lists of List<byte> which would be horribly inefficient.

    Dave

  • Monday, August 06, 2012 4:08 PM
     
      Has Code

    My point was just the way you were using e in the statement Socket.SendAsync(e), instead you do Socket.SendAsync(e.BufferList).  I was just showing basicaly how to do the casting.  It doesn't make a difference if you type cast to a List<> or an ArraySegment<>.  I also not sure there is any difference in the efficient of using either class.  I think the run time efficientcy is the same.  The casting is done as part of the compiling.  ArraySegment is just a type of List.

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
            }
            static void mycallback(EventArgs e)
            {
                ((state)e).BufferList = new List<ArraySegment<byte>>();
                int lastindex = ((state)e).BufferList.Count() - 1;
                var databuffer = ((state)e).BufferList[lastindex].Array as byte[];
            }
        }
        public class state : EventArgs
        {
            public List<ArraySegment<byte>> BufferList;
        }
    }


    jdweng

  • Monday, August 06, 2012 4:40 PM
     
     

    Why are you commenting on this thread as you have no idea what you are talking about. Do you understand anything about socket programming or the Socket or SocketAsyncEventArgs classes?

    First, Socket.SendAsync takes "SocketAsyncEventArgs" as an argument, not a BufferList.

    Second, I rarely cast anything. And it makes a huge difference what you cast to when at run time you get an exception for incorrect casts as you suggest.


    Dave

  • Monday, August 06, 2012 5:03 PM
     
     

    The "SocketAsyncEventArgs" as an argument you can pass any type object.  The object can be either a single variazble, a structure, or a class.  Usually I have seen lost of examples where people are passing a class like the code I posted.  If you rarely cast anything in C# then you are very lucky, usually when you use an EventArgs which is generic you must perform a cast in C# otherwise you get a compiler error.  Make sure you are not masking errors by turing off some off the compiler error checking.  I rather cast a variable in the code then to turning off the compiler error checking and then spend days trying to find a problem that the compiler would of reported.


    jdweng

  • Monday, August 06, 2012 5:49 PM
     
     

    I hate to be rude, but you just don't have a freeking clue Joel. You can NOT pass any type object to SendAsync, casted or not, and have it work, as Socket.SendAsync takes a "SocketAsyncEventArgs" type as an argument. Period.

    And on the subject of casting, which is a totally different subject other than what I have posted a question on, and which you seem to be focused on for some strange reason, if you are using casting as you suggest, then that is total code smell...

    Please don't post on this thread anymore as I already feel I should repost this question as you have totally polluted it with nonsense...


    Dave


    • Edited by Dave Kolb Monday, August 06, 2012 5:50 PM
    •  
  • Monday, August 06, 2012 7:03 PM
     
     
    there is a simple way of resolving this issue.  Put a break point on the Socket.SendAsync(e) statement and then add a watch item on e.  You can then see what the object e contains.  I always do this when I add a event that I've never used before to determine what the object contains.  Each type event handler is different.

    jdweng

  • Monday, August 06, 2012 7:51 PM
     
     
    There is no issue here. They arrive as SocketAsyncEventArgs objects, not anything else. It makes no sense to break on the SendAsync as I supply the argument which is, surprise, a SocketAsyncEventArgs object, which is the ONLY object it takes as a parameter.  I have no time for your nonsense trying to earn points or why ever you choose to persist this insanity. You obviously do not do socket programming, nor know ANYTHING about it, so please quit replying to this thread. You are no help whatsofreekin ever. Go away...

    Dave

  • Thursday, August 16, 2012 6:47 PM
     
     
    Anyone have any ideas or have actually used BufferList successfully?

    Dave

  • Friday, September 21, 2012 3:40 PM
     
     

    Hello Dave!

    I havent just started to use the SocketAsyncEventArgs my self and have not tryed this. But why do you do SetBuffer(null,0,0)? Wouldent the Buffer property stay null as long as you dont set it when you create the argument caus in the constructor the Buffer property will be set null and stay null as long as it dont get set..

    So remove the SetBuffer(null, 0, 0) and just give the BufferList a new list and that will be used instead of Buffer.

    Hope that will work for you if you havent solved it all ready.


    • Edited by Idar B Friday, September 21, 2012 3:41 PM
    • Edited by Idar B Friday, September 21, 2012 3:44 PM
    •  
  • Tuesday, January 01, 2013 12:54 PM
     
     Answered

    I hit the same problem. After spending a few hours, if you prepare the list before assign it to e.BufferList. It will work.

    var x = new List<ArraySegment<byte>>();

        x.Add(new ArraySegment<byte>(lTxBytes)); // add the 4 character total length
        x.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lTx.Identity))); // echo back the incoming sequence number
        x.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(lResponse)));

      e.BufferList = x;

    • Marked As Answer by Dave Kolb Tuesday, January 01, 2013 4:54 PM
    •  
  • Tuesday, January 01, 2013 4:54 PM
     
     
    Thanks for the input Idar and Alex.

    Dave