Re: Async Socket: How to tell when there is no more data.
From: Mainak Sarcar (MainakSarcar_at_discussions.microsoft.com)
Date: 03/17/05
- Next message: Abhishek Bagga: "I want to insert Image in the column headers of the Listview contol"
- Previous message: Cor Ligthert: "Re: Concurrecny error"
- In reply to: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Next in thread: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Reply: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Messages sorted by: [ date ] [ thread ]
Date: Thu, 17 Mar 2005 03:55:03 -0800
No David, your answer did not help me much..... Firstly the code that you
have written is a blocking type of code (synchronous). In a real world
application I can suspend the user interface in an indefinite loop till the
server sending data... Am I right. The correct approach is an Asynchronous
connection.
Your first part of the answer is correct... If the server disconnects the
socket then the client gets a received byte count of 0. But what if the
server does not disconnect the socket ... you as a client have to send some
command to the server to do that.
This is where my question arises. In the Receive Callback method how do I
get to know how much data to read. Data may be in a few bytes or it may be in
MBs..
Regards,
Mainak
"David Levine" wrote:
> When a sender closes the socket the receiver is notified when the received
> byte count is zero - this indicates that a graceful shutdown of the socket
> was initiated from the other end, which means that you should close the
> socket on your end to complete the shutdown. This is NOT the same as reading
> the value of the Available property. Perhaps this is what the sample code
> was intending.
>
> I use a two-phase method for determining how much data to read. The 1st
> phase sends a fixed size header block, with fields like this...
>
> struct header
> {
> int version; // and other header stuff to detect options and/or corruption
> in the sender
> int size; // size of the variable length portion of the data
> }
>
> You can put anything you like in the header but you must at least put the
> size there. Once you've read in the fixed size header, read the length of
> the data that follows. An advantage of this mechanism is that you always
> know when you've read in the entire message without needing special EOF or
> formatting characters. Also, if you ever receive bad values in the header
> you know that the sender has become corrupted and you should terminate the
> connection.
>
> Your code then implements a state machine, either at step 1 (reading header)
> or step 2 (reading data). It's quite simple and effective.
>
> Also, if you are using TCP then you should know that your call to receive
> may not get all the data in one call...you need a buffering scheme that
> reads data and adds it to a temporary buffer until the entire message has
> been received by your application. In other words, the code you posted may
> get partial strings because message boundaries are not respected. I use code
> like this (not aysnc, I use blocking calls and separate threads per
> client)...
>
> public static void Receive(Socket s,byte[] buffer)
> {
> int total = 0;
> int size = buffer.Length;
> int dataLeft = size;
> int received = 0;
> int loops = 0;
> while ( total < size )
> {
> received = s.Receive(buffer,total,dataLeft,SocketFlags.None);
> if ( received == 0 )
> return; // socket was closed by client - disconnect.
> total += received;
> dataLeft -= received;
> loops++; // diagnostics only - this can be greater then 1
> }
> } // Receive
>
> If you are using UDP then message boundaries are respected and the above
> does not apply, but I don't think that is the case because then you would
> not even need framing characters and you would not need to "know" the size
> of the incoming message.
>
> Hope this helps,
>
>
> "Mainak Sarcar" <MainakSarcar@discussions.microsoft.com> wrote in message
> news:784583CD-33D8-4E2C-B376-07ADE0C0152C@microsoft.com...
> > Very Correct... But using a terminator like that is ONLY possible if you
> > have control over what the server is sending..
> > What if I am using real world servers like POP3 or SMTP which have no
> > terminators to denote that all data has been received... I have tried
> > using
> > socket.Available property but it is unreliable... because at times it
> > gives 0
> > bytes available, but if you wait for 1-2 secs and check the property again
> > ... it has some bytes available for reading.. How would you get to know
> > when
> > to stop reading and when to call "beginReceive" method again ????
> >
> > I found this crappy code from MSDN.. which is ABSOLUTELY WRONG... the
> > program never reaches the "else" part of the code...while the socket is
> > connected.
> > private static void ReceiveCallback( IAsyncResult ar )
> > {
> > try
> > {
> > StateObject state = (StateObject) ar.AsyncState;
> > Socket client = state.workSocket;
> > int bytesRead = client.EndReceive(ar);
> >
> > if (bytesRead > 0)
> > {
> > //Get more data....
> >
> > state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
> > client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
> > new
> > AsyncCallback(ReceiveCallback), state);
> > }
> > else
> > {
> > // All the data has arrived; put it in response.
> > if (state.sb.Length > 1)
> > {
> > response = state.sb.ToString();
> > }
> > // Signal that all bytes have been received.
> > receiveDone.Set();
> > }
> > } catch (Exception e) {
> > Console.WriteLine(e.ToString());
> > }
> > }
> >
- Next message: Abhishek Bagga: "I want to insert Image in the column headers of the Listview contol"
- Previous message: Cor Ligthert: "Re: Concurrecny error"
- In reply to: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Next in thread: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Reply: David Levine: "Re: Async Socket: How to tell when there is no more data."
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|