receiving data before Socket.EndReceive()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • darthghandi@gmail.com

    #1

    receiving data before Socket.EndReceive()

    I am having mixed results with asynchronous socket receives.
    Sometimes I get the right information back from the buffer, other
    times I get some of the data that should be in the buffer printed out
    to the console. That data is printed out to the console before I even
    call Socket.EndRecei ve(). After that call, I get the rest of the data
    that wasn't printed out to the console in the buffer. Anyone have
    any idea what is going on?
    Here's the code:
    public delegate void ReceivedPacketC allBack(Packet pack);
    class PacketReceiver
    {
    private ReceivedPacketC allBack m_newPacket;
    private IOBuffer m_socketAndBuff er;
    private int m_blockSize;
    private uint m_packetSize;
    private uint m_receivedBytes ;
    private List<bytem_hold Buffer;

    public PacketReceiver( IOBuffer theSockBuff, int blockSize)
    {
    m_socketAndBuff er = theSockBuff;
    m_blockSize = blockSize;
    m_socketAndBuff er.ClearBuffer( );
    m_packetSize = 0;
    m_receivedBytes = 0;
    //m_holdBuffer = new List<byte>();
    }

    public void NeedPacket(Rece ivedPacketCallB ack pack)
    {
    m_newPacket = pack;
    }

    //should make sure that we receive one and only one packet
    public void ReceivePacket()
    {
    m_socketAndBuff er.ClearBuffer( );
    if (m_socketAndBuf fer.IsConnected )
    {
    AsyncCallback callMe = new
    AsyncCallback(R eceiveCallBack) ;
    m_socketAndBuff er.ResizeByteBu ffer((uint)m_bl ockSize);
    Console.WriteLi ne("The Buffer is " +
    m_socketAndBuff er.m_buffer.Cou nt + " big in bytes.");

    m_socketAndBuff er.m_sockMe.Beg inReceive(m_soc ketAndBuffer.m_ buffer,
    SocketFlags.Non e, callMe, m_socketAndBuff er);
    }
    else
    {
    throw new Exception("The socket is no longer
    connected.");
    }
    }

    private void ReceiveCallBack (IAsyncResult ar)
    {
    m_socketAndBuff er = (IOBuffer)ar.As yncState;
    if (m_socketAndBuf fer.IsConnected )
    {
    m_receivedBytes =
    (uint)m_socketA ndBuffer.m_sock Me.EndReceive(a r);
    m_holdBuffer = new List<byte>((int )m_receivedByte s);

    m_holdBuffer.Ad dRange(m_socket AndBuffer.m_buf fer[0].Array);
    m_socketAndBuff er.ClearBuffer( );
    m_packetSize = Packet.ReadInt3 2FromBytes(m_ho ldBuffer,
    0);
    Console.WriteLi ne("The packet size is " + m_packetSize
    + "");
    UInt32 bytesLeft = m_packetSize - (uint)(m_blockS ize -
    4);
    Console.WriteLi ne("We need to read " + bytesLeft + "
    more bytes.");
    if (bytesLeft 512000000)
    {
    Console.WriteLi ne("size to big");
    }
    m_socketAndBuff er.ResizeByteBu ffer(bytesLeft) ;

    AsyncCallback callme = new
    AsyncCallback(C reatePacket);

    m_socketAndBuff er.m_sockMe.Beg inReceive(m_soc ketAndBuffer.m_ buffer,
    SocketFlags.Non e, callme, m_socketAndBuff er);
    }
    }

    private void CreatePacket(IA syncResult ar)
    {
    m_socketAndBuff er = (IOBuffer)ar.As yncState;
    if (m_socketAndBuf fer.IsConnected )
    {
    m_receivedBytes +=
    (uint)m_socketA ndBuffer.m_sock Me.EndReceive(a r);

    m_holdBuffer.Ad dRange(m_socket AndBuffer.m_buf fer[0].Array);
    if (m_receivedByte s < (m_packetSize + 4))
    {
    uint leftOver = m_receivedBytes - m_packetSize +
    4;
    m_socketAndBuff er.ResizeByteBu ffer(leftOver);
    AsyncCallback callMeNow = new
    AsyncCallback(C reatePacket);

    m_socketAndBuff er.m_sockMe.Beg inReceive(m_soc ketAndBuffer.m_ buffer,
    SocketFlags.Non e, callMeNow, m_socketAndBuff er);
    }
    Packet thePacket = Packet.ParseByt es(m_holdBuffer ,
    m_blockSize);
    m_newPacket(the Packet); //send the packet to
    whoever needs it (delegate)
    }
    }
    }

  • Peter Duniho

    #2
    Re: receiving data before Socket.EndRecei ve()

    darthghandi@gma il.com wrote:
    I am having mixed results with asynchronous socket receives.
    Sometimes I get the right information back from the buffer, other
    times I get some of the data that should be in the buffer printed out
    to the console. That data is printed out to the console before I even
    call Socket.EndRecei ve(). After that call, I get the rest of the data
    that wasn't printed out to the console in the buffer. Anyone have
    any idea what is going on?
    Here's the code:
    That is both not enough code and too much, all at the same time. You
    are missing half of the connection (the sending side) as well as the
    implementation of IOBuffer, and as well you have included a fair amount
    of code that is likely not necessary to reproduce the issue (in fact,
    unless IOBuffer is directly related to the problem, you should post code
    that doesn't even include it).

    And you have not precisely described what the actual problem is. What
    output do you get, and what output do you expect instead?

    So, if you really want someone to spend more than a few moments with
    your code, you should distill it down into something that is
    concise-but-complete while reliably reproducing the problem. Post that
    along with a precise problem description.

    That said, as near as I can tell from my quick scan of your code, you
    appear to deliver an assembled "packet" whether it's completed or not.
    I would expect that to be a problem.

    There are plenty of other things I would change about the code, but that
    stands out as being particularly likely to produce incorrect results.

    Pete

    Comment

    • darthghandi@gmail.com

      #3
      Re: receiving data before Socket.EndRecei ve()

      On Aug 2, 8:44 pm, Peter Duniho <NpOeStPe...@Nn OwSlPiAnMk.comw rote:
      darthgha...@gma il.com wrote:
      I am having mixed results with asynchronous socket receives.
      Sometimes I get the right information back from the buffer, other
      times I get some of the data that should be in the buffer printed out
      to the console. That data is printed out to the console before I even
      call Socket.EndRecei ve(). After that call, I get the rest of the data
      that wasn't printed out to the console in the buffer. Anyone have
      any idea what is going on?
      Here's the code:
      >
      That is both not enough code and too much, all at the same time. You
      are missing half of the connection (the sending side) as well as the
      implementation of IOBuffer, and as well you have included a fair amount
      of code that is likely not necessary to reproduce the issue (in fact,
      unless IOBuffer is directly related to the problem, you should post code
      that doesn't even include it).
      >
      And you have not precisely described what the actual problem is. What
      output do you get, and what output do you expect instead?
      >
      So, if you really want someone to spend more than a few moments with
      your code, you should distill it down into something that is
      concise-but-complete while reliably reproducing the problem. Post that
      along with a precise problem description.
      >
      That said, as near as I can tell from my quick scan of your code, you
      appear to deliver an assembled "packet" whether it's completed or not.
      I would expect that to be a problem.
      >
      There are plenty of other things I would change about the code, but that
      stands out as being particularly likely to produce incorrect results.
      >
      Pete
      Here is the section of code where I use the PacketReceiver:
      private void EndStart(IAsync Result ar)
      {
      Socket temp = (Socket)ar.Asyn cState;
      if (temp.Connected )
      {
      int sentBytes = temp.EndSend(ar );
      List<ArraySegme nt<byte>tempBuf fer = new
      List<ArraySegme nt<byte>>();
      tempBuffer.Add( new ArraySegment<by te>(new byte[255]));
      receiveBuffer.m _buffer = tempBuffer;
      AsyncCallback callMe = new
      AsyncCallback(E ndReceiveVersio nString);

      receiveBuffer.m _sockMe.BeginRe ceive(receiveBu ffer.m_buffer,
      SocketFlags.Non e, callMe, receiveBuffer);
      }
      }

      private void EndReceiveVersi on(IAsyncResult ar)
      {
      Encoder theEncoder = new Encoder();
      IOBuffer temp = (IOBuffer)ar.As yncState;
      if (temp.m_sockMe. Connected)
      {
      int receivedBytes = temp.m_sockMe.E ndReceive(ar);

      Packet sendAlgs = new Packet();
      sendAlgs.Fill(s endData);
      ArraySegment<by tetoBuff = new
      ArraySegment<by te>(sendAlgs.Ge tPacketInBytes( ));
      sendBuffer.m_bu ffer.Add(toBuff );
      sendBuffer.m_so ckMe.BeginSend( sendBuffer.m_bu ffer,
      SocketFlags.Non e, callMe, sendBuffer);
      }
      }
      I have not experienced problems sending, just receiving. The output I
      am seeing in the console is data sent from the client, but only the
      first part of it. The rest of the data sent from the client is in the
      buffer like it should be. The packet is assembled by first reading
      the length (which should be the first of the packet), then doing
      another receive call to get the rest of the packet. Since some of the
      data received is sent to the console instead of the buffer, I get a
      bad length when I try to do the second receive call. For example, if
      the client sends a packet like this:
      23somedata
      the console would display the following (which it shouldn't):
      23som
      and the buffer would contain:
      edata
      Does that make sense?
      Thanks for your time.

      Comment

      • darthghandi@gmail.com

        #4
        Re: receiving data before Socket.EndRecei ve()

        On Aug 2, 9:43 pm, darthgha...@gma il.com wrote:
        On Aug 2, 8:44 pm, Peter Duniho <NpOeStPe...@Nn OwSlPiAnMk.comw rote:
        >
        darthgha...@gma il.com wrote:
        I am having mixed results with asynchronous socket receives.
        Sometimes I get the right information back from the buffer, other
        times I get some of the data that should be in the buffer printed out
        to the console. That data is printed out to the console before I even
        call Socket.EndRecei ve(). After that call, I get the rest of the data
        that wasn't printed out to the console in the buffer. Anyone have
        any idea what is going on?
        Here's the code:
        >
        That is both not enough code and too much, all at the same time. You
        are missing half of the connection (the sending side) as well as the
        implementation of IOBuffer, and as well you have included a fair amount
        of code that is likely not necessary to reproduce the issue (in fact,
        unless IOBuffer is directly related to the problem, you should post code
        that doesn't even include it).
        >
        And you have not precisely described what the actual problem is. What
        output do you get, and what output do you expect instead?
        >
        So, if you really want someone to spend more than a few moments with
        your code, you should distill it down into something that is
        concise-but-complete while reliably reproducing the problem. Post that
        along with a precise problem description.
        >
        That said, as near as I can tell from my quick scan of your code, you
        appear to deliver an assembled "packet" whether it's completed or not.
        I would expect that to be a problem.
        >
        There are plenty of other things I would change about the code, but that
        stands out as being particularly likely to produce incorrect results.
        >
        Pete
        >
        Here is the section of code where I use the PacketReceiver:
        private void EndStart(IAsync Result ar)
        {
        Socket temp = (Socket)ar.Asyn cState;
        if (temp.Connected )
        {
        int sentBytes = temp.EndSend(ar );
        List<ArraySegme nt<byte>tempBuf fer = new
        List<ArraySegme nt<byte>>();
        tempBuffer.Add( new ArraySegment<by te>(new byte[255]));
        receiveBuffer.m _buffer = tempBuffer;
        AsyncCallback callMe = new
        AsyncCallback(E ndReceiveVersio nString);
        >
        receiveBuffer.m _sockMe.BeginRe ceive(receiveBu ffer.m_buffer,
        SocketFlags.Non e, callMe, receiveBuffer);
        }
        }
        >
        private void EndReceiveVersi on(IAsyncResult ar)
        {
        Encoder theEncoder = new Encoder();
        IOBuffer temp = (IOBuffer)ar.As yncState;
        if (temp.m_sockMe. Connected)
        {
        int receivedBytes = temp.m_sockMe.E ndReceive(ar);
        >
        Packet sendAlgs = new Packet();
        sendAlgs.Fill(s endData);
        ArraySegment<by tetoBuff = new
        ArraySegment<by te>(sendAlgs.Ge tPacketInBytes( ));
        sendBuffer.m_bu ffer.Add(toBuff );
        sendBuffer.m_so ckMe.BeginSend( sendBuffer.m_bu ffer,
        SocketFlags.Non e, callMe, sendBuffer);
        }
        }
        I have not experienced problems sending, just receiving. The output I
        am seeing in the console is data sent from the client, but only the
        first part of it. The rest of the data sent from the client is in the
        buffer like it should be. The packet is assembled by first reading
        the length (which should be the first of the packet), then doing
        another receive call to get the rest of the packet. Since some of the
        data received is sent to the console instead of the buffer, I get a
        bad length when I try to do the second receive call. For example, if
        the client sends a packet like this:
        23somedata
        the console would display the following (which it shouldn't):
        23som
        and the buffer would contain:
        edata
        Does that make sense?
        Thanks for your time.
        Also, please feel free to make suggestions on how I can improve my
        code. I'm really new to this and would appreciate any tips anyone
        might have. If there are any good books on sockets or writing good
        code please feel free to suggest them.
        Thanks for your time.

        Comment

        • Peter Duniho

          #5
          Re: receiving data before Socket.EndRecei ve()

          darthghandi@gma il.com wrote:
          [...]
          Now comes the hard
          part, the redesign. Would it be better to read one byte at a time
          looking for line feed or read chunks looking for the same thing and
          saving the rest? If anyone knows of some good examples or articles on
          good ways to design this type of thing please feel free to suggest
          them.
          Generally speaking, you should receive larger blocks at a time, to make
          most efficient use of the network i/o. Then you can parcel that data
          out as needed to the actual application end of things.

          As another suggestion regarding your code: IMHO, it's not a good idea to
          have two different receive callbacks. I understand that you have
          different things to do when receiving the data, and that's what led to
          the two different callbacks. But your network i/o should be more
          separated from the application logic than that (see above).

          Even once you get things separated better, IMHO it will still make more
          sense to have a general-purpose application data-handling method, but at
          least if you don't do it that way, your actual network i/o code remains
          simple.

          Pete

          Comment

          • darthghandi@gmail.com

            #6
            Re: receiving data before Socket.EndRecei ve()

            On Aug 3, 2:58 pm, Peter Duniho <NpOeStPe...@Nn OwSlPiAnMk.comw rote:
            darthgha...@gma il.com wrote:
            [...]
            Now comes the hard
            part, the redesign. Would it be better to read one byte at a time
            looking for line feed or read chunks looking for the same thing and
            saving the rest? If anyone knows of some good examples or articles on
            good ways to design this type of thing please feel free to suggest
            them.
            >
            Generally speaking, you should receive larger blocks at a time, to make
            most efficient use of the network i/o. Then you can parcel that data
            out as needed to the actual application end of things.
            >
            As another suggestion regarding your code: IMHO, it's not a good idea to
            have two different receive callbacks. I understand that you have
            different things to do when receiving the data, and that's what led to
            the two different callbacks. But your network i/o should be more
            separated from the application logic than that (see above).
            >
            Even once you get things separated better, IMHO it will still make more
            sense to have a general-purpose application data-handling method, but at
            least if you don't do it that way, your actual network i/o code remains
            simple.
            >
            Pete
            I'll give that a shot. Thanks again for your time.

            Comment

            • Chris Mullins [MVP]

              #7
              Re: receiving data before Socket.EndRecei ve()

              You're trying to do the same sorts of things we do in our XMPP SDK.

              We read from the various socket streams, parse out XML Fragments, turn them
              into packets, match them against classes, instantiate the right object,
              serialize the xml into the object, and then raise the correct event.

              Our SDK has source code available, and you can pull it down and look at how
              we're doing everything:


              What you're looking for is (mostly) found in the two classes:
              Coversant.SoapB ox.Base.XMPPSoc ket
              Coversant.SoapB ox.Base.XMLStre amReceiver

              Our approach is very scalable, and quite reliable. Our use of socket buffers
              that comes out of a buffer pool for reads/write, minimizes heap
              fragmentation.

              --
              Chris Mullins, MCSD.NET, MCPD:Enterprise , Microsoft C# MVP
              Find your domain name at HugeDomains. Start using this domain right away.


              <darthghandi@gm ail.comwrote in message
              news:1186106662 .788373.10640@e 16g2000pri.goog legroups.com...
              >I am having mixed results with asynchronous socket receives.
              Sometimes I get the right information back from the buffer, other
              times I get some of the data that should be in the buffer printed out
              to the console. That data is printed out to the console before I even
              call Socket.EndRecei ve(). After that call, I get the rest of the data
              that wasn't printed out to the console in the buffer. Anyone have
              any idea what is going on?

              Comment

              • darthghandi@gmail.com

                #8
                Re: receiving data before Socket.EndRecei ve()

                On Aug 3, 4:29 pm, "Chris Mullins [MVP]" <cmull...@yahoo .comwrote:
                You're trying to do the same sorts of things we do in our XMPP SDK.
                >
                We read from the various socket streams, parse out XML Fragments, turn them
                into packets, match them against classes, instantiate the right object,
                serialize the xml into the object, and then raise the correct event.
                >
                Our SDK has source code available, and you can pull it down and look at how
                we're doing everything:http://developers.coversant.net/Down...3/Default.aspx
                >
                What you're looking for is (mostly) found in the two classes:
                Coversant.SoapB ox.Base.XMPPSoc ket
                Coversant.SoapB ox.Base.XMLStre amReceiver
                >
                Our approach is very scalable, and quite reliable. Our use of socket buffers
                that comes out of a buffer pool for reads/write, minimizes heap
                fragmentation.
                >
                --
                Chris Mullins, MCSD.NET, MCPD:Enterprise , Microsoft C# MVPhttp://www.coversant.c om/blogs/cmullins
                >
                <darthgha...@gm ail.comwrote in message
                >
                news:1186106662 .788373.10640@e 16g2000pri.goog legroups.com...
                >
                I am having mixed results with asynchronous socket receives.
                Sometimes I get the right information back from the buffer, other
                times I get some of the data that should be in the buffer printed out
                to the console. That data is printed out to the console before I even
                call Socket.EndRecei ve(). After that call, I get the rest of the data
                that wasn't printed out to the console in the buffer. Anyone have
                any idea what is going on?
                Thank you. I'll take a look at that over the weekend and see what I
                can learn from it.
                Thanks again for the time.

                Comment

                Working...