PC Review


Reply
Thread Tools Rate Thread

BeginReceive return zero length buffer when run ,and work correctly when use step by step debug mode

 
 
Daniel
Guest
Posts: n/a
 
      15th Sep 2006
Bit confused by what you are saying is the problem but can you calrify.

If you send an object to the other client, it is not always getting there.
But if you debug, it does? Is the problem that you are 'losing' bytes?


"semedao" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi , I am using asyc sockets p2p connection between 2 clients.
> when I debug step by step the both sides , i'ts work ok.
> when I run it , in somepoint (same location in the code)
> when I want to receive 5 bytes buffer , I call the BeginReceive and then
> wait on AsyncWaitHandle.WaitOne()
> but it is signald imidiatly , and the next call to EndReceive return zero
> bytes length , also the buffer is empty.
> here is the code:
> public static byte[] Receive(Socket OpenSocket, int length)
>
> {
>
> byte[] buffer = new byte[length];
>
> int totalreceive = 0;
>
> int _lastReceive = 0;
>
> if (OpenSocket.Blocking)
>
> totalreceive = OpenSocket.Receive(buffer);
>
> else
>
> {
>
> IAsyncResult ar;
>
> do
>
> {
>
> //in this point the OpenSocket.Available == 0 !
>
> ar = OpenSocket.BeginReceive(buffer, 0, length, SocketFlags.None, null,
> null);
>
> ar.AsyncWaitHandle.WaitOne(); // something "signald it before data
> received?
>
> _lastReceive = OpenSocket.EndReceive(ar);
>
> if (_lastReceive == 0) // happen when run the code , doeas not happen if
> step by step slowly!
>
> {
>
> buffer = null;
>
> throw new Exception("No data receive");
>
> }
>
> totalreceive += _lastReceive;
>
> } while (totalreceive < length);
>
> }
>
> return buffer;
>
> }
>
> what is my problem ? I don't want to use sync calls because the rest of
> the session is async also , so I only want to makethe async - sinc like
> forthis part ofthe code , also , when in the debug mode I change the
> OpenSocket.Blocking to True - cause it to call sync receive instead of
> beginrecv , also return with zero length buffer
>
>
>
> any ideas ?
>
>



 
Reply With Quote
 
 
 
 
semedao
Guest
Posts: n/a
 
      15th Sep 2006
Hi , I am using asyc sockets p2p connection between 2 clients.
when I debug step by step the both sides , i'ts work ok.
when I run it , in somepoint (same location in the code)
when I want to receive 5 bytes buffer , I call the BeginReceive and then
wait on AsyncWaitHandle.WaitOne()
but it is signald imidiatly , and the next call to EndReceive return zero
bytes length , also the buffer is empty.
here is the code:
public static byte[] Receive(Socket OpenSocket, int length)

{

byte[] buffer = new byte[length];

int totalreceive = 0;

int _lastReceive = 0;

if (OpenSocket.Blocking)

totalreceive = OpenSocket.Receive(buffer);

else

{

IAsyncResult ar;

do

{

//in this point the OpenSocket.Available == 0 !

ar = OpenSocket.BeginReceive(buffer, 0, length, SocketFlags.None, null,
null);

ar.AsyncWaitHandle.WaitOne(); // something "signald it before data received?

_lastReceive = OpenSocket.EndReceive(ar);

if (_lastReceive == 0) // happen when run the code , doeas not happen if
step by step slowly!

{

buffer = null;

throw new Exception("No data receive");

}

totalreceive += _lastReceive;

} while (totalreceive < length);

}

return buffer;

}

what is my problem ? I don't want to use sync calls because the rest of the
session is async also , so I only want to makethe async - sinc like forthis
part ofthe code , also , when in the debug mode I change the
OpenSocket.Blocking to True - cause it to call sync receive instead of
beginrecv , also return with zero length buffer



any ideas ?


 
Reply With Quote
 
semedao
Guest
Posts: n/a
 
      15th Sep 2006
No,
I have some send recv conversation between 2 clients
the mode is async sockets.
when I come to some location in the code that I want to recv 5 bytes , the
recv return before the bytes received , the length of the EndRecv() is 0
(zero) ,
I use the async result of the BeginReceive() WaitHandle.WaitOne() to block
on this thread until the bytes come , but , it does not block and return as
I described above.
When I debug this process of the both clients STEP by STEP , it's work
correctly and return those 5 bytes !
so , I can't find whay it's happen !
"Daniel" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Bit confused by what you are saying is the problem but can you calrify.
>
> If you send an object to the other client, it is not always getting there.
> But if you debug, it does? Is the problem that you are 'losing' bytes?
>
>
> "semedao" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Hi , I am using asyc sockets p2p connection between 2 clients.
>> when I debug step by step the both sides , i'ts work ok.
>> when I run it , in somepoint (same location in the code)
>> when I want to receive 5 bytes buffer , I call the BeginReceive and then
>> wait on AsyncWaitHandle.WaitOne()
>> but it is signald imidiatly , and the next call to EndReceive return zero
>> bytes length , also the buffer is empty.
>> here is the code:
>> public static byte[] Receive(Socket OpenSocket, int length)
>>
>> {
>>
>> byte[] buffer = new byte[length];
>>
>> int totalreceive = 0;
>>
>> int _lastReceive = 0;
>>
>> if (OpenSocket.Blocking)
>>
>> totalreceive = OpenSocket.Receive(buffer);
>>
>> else
>>
>> {
>>
>> IAsyncResult ar;
>>
>> do
>>
>> {
>>
>> //in this point the OpenSocket.Available == 0 !
>>
>> ar = OpenSocket.BeginReceive(buffer, 0, length, SocketFlags.None, null,
>> null);
>>
>> ar.AsyncWaitHandle.WaitOne(); // something "signald it before data
>> received?
>>
>> _lastReceive = OpenSocket.EndReceive(ar);
>>
>> if (_lastReceive == 0) // happen when run the code , doeas not happen if
>> step by step slowly!
>>
>> {
>>
>> buffer = null;
>>
>> throw new Exception("No data receive");
>>
>> }
>>
>> totalreceive += _lastReceive;
>>
>> } while (totalreceive < length);
>>
>> }
>>
>> return buffer;
>>
>> }
>>
>> what is my problem ? I don't want to use sync calls because the rest of
>> the session is async also , so I only want to makethe async - sinc like
>> forthis part ofthe code , also , when in the debug mode I change the
>> OpenSocket.Blocking to True - cause it to call sync receive instead of
>> beginrecv , also return with zero length buffer
>>
>>
>>
>> any ideas ?
>>
>>

>
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      15th Sep 2006
"semedao" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> [...]
> I use the async result of the BeginReceive() WaitHandle.WaitOne() to block
> on this thread until the bytes come , but , it does not block and return
> as I described above.
> When I debug this process of the both clients STEP by STEP , it's work
> correctly and return those 5 bytes !
> so , I can't find whay it's happen !


Disclaimer: while I've done plenty of Winsock programming, I haven't used
sockets in .NET yet. Still, I have what I think is a good guess as to
what's going on...

I believe that you misunderstand what the behavior of Begin/EndReceive is
(possibly because the documentation is misleading or incorrect). In
particular, assuming it works like the other async stuff in .NET, it does
NOT actually wait for data to be present on a non-blocking socket when you
wait on the AsyncResult or call EndReceive). All it does is cause the
particular call to Receive to happen on a different thread so that your own
thread can continue working. But in the other thread, it's like calling
Receive directly. There's no additional processing to check for data being
available.

So, in this case you've got a non-blocking socket, and the receive operation
completes essentially immediately since there's no data, and when you check
the results there is no data.

By stepping through (or probably any other delay), you allow time for the
data to get into the socket's receive buffer and become available to receive
in your thread.

In other words, using BeginReceive instead of Receive only makes sense if
you have a blocking socket. If you have a non-blocking socket, you need to
continue to use the normal i/o notification mechanism that you've chosen for
use with that socket.

IMHO, it's a little odd that EndReceive returns a value. If it were
completely analogous to the normal Winsock behavior, it'd throw (or return,
in the overload that returns an exception as a parameter) an exception when
no data is present (whatever the equivalent to WSAEWOULDBLOCK is...that is,
a SocketException where ErrorCode is set to WSAEWOULDBLOCK).

I realize that all of the above is in direct contradiction to the
documentation (in particular, the documentation for EndReceive reads in part
"The EndReceive method will block until data is available"). But given the
behavior you're seeing, and given how Winsock (the underlying Win32 API)
actually works, I think it's more likely that the documentation is wrong.
Making EndReceive blocking on a non-blocking socket would be non-trivial
(though not terribly difficult) and doing so would significantly reduce the
uniformity of the behavior of "End..." functions.

All that said, a quick look through the .NET Sockets documentation didn't
turn up anything that I recognized as a normal use of a non-blocking socket
other than Select. That is, you can get and set the Blocking property, but
I don't see any means other than calling Sockets.Select to find out when
it's reasonable to call Receive or Send on a socket. So to address the
above, the only solution I can see is to use the Select method to wait until
the socket becomes readable (and of course, depending on the .NET
implementation of Select, you may have to loop until you get the data you
want (or any data at all for that matter...in Winsock, calling select() does
not guarantee that when you get to the call to recv() you will actually get
any data back, even though most often that is the case).

If you are using the Blocking property, I assume that you actually know
about Select and any other mechanism that is similar, so hopefully there's
enough information here for you to get things working.

Pete


 
Reply With Quote
 
Daniel
Guest
Posts: n/a
 
      15th Sep 2006
Hello again,

I didn't read all of Peters reply but he did mention the delay fixing it.
Also you said 'no' to my comment that your 'losing data.

Well if when you debug you receive 5 bytes and when you don't debug you
don't recive 5 bytes....haven't you lost data?

the fatc you reminded me you are using async sockets makes me think your new
to it.

I have written commerical software using async sockets in .net 2.0 and when
i was learning i had the exact same problem,.

What i didn't know at the time was a few key things:

1) data will never go out of order
2) you will never lose bytes
3) you may receive all your data in one stream call

So say you sent 10 bytes, then 5 bytes then 5 more bytes

Your endreceive may return : 20bytes.......it may return 10, then 5 then
5...(as in when there is a delay due to debugging), or it may return 15 then
5.

When i had the sam problem as you it was because i was doing the end reieve,
reading the received bytes, then breaking out of my loop and waiting for
more data on the socket. That point where i broke i lost remining data. So
only when the correct amount came through in one call did i get it all.
Sound slike your issue.

So make sure you read very byte that comes in. If your buffer is 1024 bytes
and you receive 1024 bytes, read them all. And be sure to send the size
expected along too. So you know how much to read of each object sent. And
remmber you need to handle overlap.

For example if your buffer is 1024 bytes in size and you have an object of
1023 bytes and you alway send the first 4 bytes before any send as the size
of data to come, then the 1024th byte, and then the 1st, 2nd and 3rd bytes
of the next receive will be that 4byts size of the next data block coming
in.

If what i say above confuses then re-read sockets, your understanding is
flawes. As i say Peter may have already explained this to you.



"Peter Duniho" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "semedao" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> [...]
>> I use the async result of the BeginReceive() WaitHandle.WaitOne() to
>> block on this thread until the bytes come , but , it does not block and
>> return as I described above.
>> When I debug this process of the both clients STEP by STEP , it's work
>> correctly and return those 5 bytes !
>> so , I can't find whay it's happen !

>
> Disclaimer: while I've done plenty of Winsock programming, I haven't used
> sockets in .NET yet. Still, I have what I think is a good guess as to
> what's going on...
>
> I believe that you misunderstand what the behavior of Begin/EndReceive is
> (possibly because the documentation is misleading or incorrect). In
> particular, assuming it works like the other async stuff in .NET, it does
> NOT actually wait for data to be present on a non-blocking socket when you
> wait on the AsyncResult or call EndReceive). All it does is cause the
> particular call to Receive to happen on a different thread so that your
> own thread can continue working. But in the other thread, it's like
> calling Receive directly. There's no additional processing to check for
> data being available.
>
> So, in this case you've got a non-blocking socket, and the receive
> operation completes essentially immediately since there's no data, and
> when you check the results there is no data.
>
> By stepping through (or probably any other delay), you allow time for the
> data to get into the socket's receive buffer and become available to
> receive in your thread.
>
> In other words, using BeginReceive instead of Receive only makes sense if
> you have a blocking socket. If you have a non-blocking socket, you need
> to continue to use the normal i/o notification mechanism that you've
> chosen for use with that socket.
>
> IMHO, it's a little odd that EndReceive returns a value. If it were
> completely analogous to the normal Winsock behavior, it'd throw (or
> return, in the overload that returns an exception as a parameter) an
> exception when no data is present (whatever the equivalent to
> WSAEWOULDBLOCK is...that is, a SocketException where ErrorCode is set to
> WSAEWOULDBLOCK).
>
> I realize that all of the above is in direct contradiction to the
> documentation (in particular, the documentation for EndReceive reads in
> part "The EndReceive method will block until data is available"). But
> given the behavior you're seeing, and given how Winsock (the underlying
> Win32 API) actually works, I think it's more likely that the documentation
> is wrong. Making EndReceive blocking on a non-blocking socket would be
> non-trivial (though not terribly difficult) and doing so would
> significantly reduce the uniformity of the behavior of "End..." functions.
>
> All that said, a quick look through the .NET Sockets documentation didn't
> turn up anything that I recognized as a normal use of a non-blocking
> socket other than Select. That is, you can get and set the Blocking
> property, but I don't see any means other than calling Sockets.Select to
> find out when it's reasonable to call Receive or Send on a socket. So to
> address the above, the only solution I can see is to use the Select method
> to wait until the socket becomes readable (and of course, depending on the
> .NET implementation of Select, you may have to loop until you get the data
> you want (or any data at all for that matter...in Winsock, calling
> select() does not guarantee that when you get to the call to recv() you
> will actually get any data back, even though most often that is the case).
>
> If you are using the Blocking property, I assume that you actually know
> about Select and any other mechanism that is similar, so hopefully there's
> enough information here for you to get things working.
>
> Pete
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      15th Sep 2006
"Daniel" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> I didn't read all of Peters reply but he did mention the delay fixing it.
> Also you said 'no' to my comment that your 'losing data.
>
> Well if when you debug you receive 5 bytes and when you don't debug you
> don't recive 5 bytes....haven't you lost data?


Not necessarily. All we know is that he doesn't receive the data when he
expected to. Since he has no loop around his receive attempt, he definitely
will fail to read the data if it's not read the first time through. But the
data remains on the socket, until such time as it IS read or the socket is
closed. It's entirely possible that his code does eventually read the data,
preventing it from being lost.

I'd say if he says he doesn't lose data, we should take his word for it, at
least for the moment.

In addition...

> the fatc you reminded me you are using async sockets makes me think your
> new to it.
>
> I have written commerical software using async sockets in .net 2.0 and
> when i was learning i had the exact same problem,.
>
> What i didn't know at the time was a few key things:
>
> 1) data will never go out of order
> 2) you will never lose bytes
> 3) you may receive all your data in one stream call
>
> So say you sent 10 bytes, then 5 bytes then 5 more bytes
>
> Your endreceive may return : 20bytes.......it may return 10, then 5 then
> 5...(as in when there is a delay due to debugging), or it may return 15
> then 5.


All true. However, the thing that many programmers miss (and which you
didn't mention) is that you may not even receive 10 bytes or 5 bytes or any
given number of bytes for any given call to receive.

In your example, the sender sends 20 bytes. The receiver may in fact wind
up receiving 1 byte at a time, 20 times, and the code must be prepared to
deal with this. In reality, the extreme cases almost never happen (eg
getting just one byte at a time) but the API specification doesn't guarantee
anything better than that, and if your code isn't handling that degenerate
case, it likely also doesn't handle the more likely cases as well.

With a stream-oriented socket (eg TCP), there are no message boundaries.
The way the data is grouped during the send has nothing to do with the way
the data is grouped during the receive.

Now, as it happens, we don't really know whether the original poster is
using a stream-oriented socket. I didn't see anything in his post or code
that implies TCP (or similar protocol). If he's using UDP, all of the above
isn't relevant and there's a whole different set of considerations (ie, one
receive always returns exactly what one send sent, but you may receive the
same datagram more than once, not at all, or out of order from the other
datagrams).

The real issue here appears to be what "blocking" and "non-blocking" mean
with respect to the .NET implementation of sockets. I suspect that even
though the documentation says otherwise, the EndReceive method only blocks
until the receive is completed when a blocking socket is used (and of
course, as you point out, for a TCP socket "complete" does not necessary
mean "the buffer has been filled"...it just means *some* data has been
received).

Pete


 
Reply With Quote
 
semedao
Guest
Posts: n/a
 
      16th Sep 2006
Hi , I take back my words about missing data... )
ok ok , the data is missing , but , help me understand
why ??
firsy - yes , I am using TCP
now , If I made loop around the "beginRecv until it will return the expected
buffer length , the app is in infinite loop in case when the return of
endrecv is zero.
so , how can I handle it ?

"Peter Duniho" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Daniel" <(E-Mail Removed)> wrote in message
> news:%(E-Mail Removed)...
>> I didn't read all of Peters reply but he did mention the delay fixing it.
>> Also you said 'no' to my comment that your 'losing data.
>>
>> Well if when you debug you receive 5 bytes and when you don't debug you
>> don't recive 5 bytes....haven't you lost data?

>
> Not necessarily. All we know is that he doesn't receive the data when he
> expected to. Since he has no loop around his receive attempt, he
> definitely will fail to read the data if it's not read the first time
> through. But the data remains on the socket, until such time as it IS
> read or the socket is closed. It's entirely possible that his code does
> eventually read the data, preventing it from being lost.
>
> I'd say if he says he doesn't lose data, we should take his word for it,
> at least for the moment.
>
> In addition...
>
>> the fatc you reminded me you are using async sockets makes me think your
>> new to it.
>>
>> I have written commerical software using async sockets in .net 2.0 and
>> when i was learning i had the exact same problem,.
>>
>> What i didn't know at the time was a few key things:
>>
>> 1) data will never go out of order
>> 2) you will never lose bytes
>> 3) you may receive all your data in one stream call
>>
>> So say you sent 10 bytes, then 5 bytes then 5 more bytes
>>
>> Your endreceive may return : 20bytes.......it may return 10, then 5 then
>> 5...(as in when there is a delay due to debugging), or it may return 15
>> then 5.

>
> All true. However, the thing that many programmers miss (and which you
> didn't mention) is that you may not even receive 10 bytes or 5 bytes or
> any given number of bytes for any given call to receive.
>
> In your example, the sender sends 20 bytes. The receiver may in fact wind
> up receiving 1 byte at a time, 20 times, and the code must be prepared to
> deal with this. In reality, the extreme cases almost never happen (eg
> getting just one byte at a time) but the API specification doesn't
> guarantee anything better than that, and if your code isn't handling that
> degenerate case, it likely also doesn't handle the more likely cases as
> well.
>
> With a stream-oriented socket (eg TCP), there are no message boundaries.
> The way the data is grouped during the send has nothing to do with the way
> the data is grouped during the receive.
>
> Now, as it happens, we don't really know whether the original poster is
> using a stream-oriented socket. I didn't see anything in his post or code
> that implies TCP (or similar protocol). If he's using UDP, all of the
> above isn't relevant and there's a whole different set of considerations
> (ie, one receive always returns exactly what one send sent, but you may
> receive the same datagram more than once, not at all, or out of order from
> the other datagrams).
>
> The real issue here appears to be what "blocking" and "non-blocking" mean
> with respect to the .NET implementation of sockets. I suspect that even
> though the documentation says otherwise, the EndReceive method only blocks
> until the receive is completed when a blocking socket is used (and of
> course, as you point out, for a TCP socket "complete" does not necessary
> mean "the buffer has been filled"...it just means *some* data has been
> received).
>
> Pete
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      16th Sep 2006
"semedao" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi , I take back my words about missing data... )
> ok ok , the data is missing , but , help me understand
> why ??


At what point is it missing? Do you ever try to read from the socket again
after getting a 0 return value from EndReceive and throwing an exception? I
think that's an important clarification.

> firsy - yes , I am using TCP
> now , If I made loop around the "beginRecv until it will return the
> expected buffer length , the app is in infinite loop in case when the
> return of endrecv is zero.
> so , how can I handle it ?


oopsie on my part. I didn't notice you had the whole non-blocking scenario
wrapped in a do/while loop. I think your loop is fine (except that it
didn't include the blocking case), and should in fact keep control within
the loop until you've read sufficient data (as long as you don't throw an
exception, so the first step is to take that out as a response to receiving
a 0 return value).

Secondly, I would forget (at least for the moment) using Begin/EndReceive.
I think it's an unnecessary distraction, especially since you want your code
to block anyway. Use a regular Receive. With a non-blocking socket, you'll
want to also call Socket.Select to block your thread until data is available
on the socket. Since I haven't used .NET sockets, I don't really know
whether you're using the Begin/EndReceive functions correctly, but they seem
to me to be unneeded here, since you don't intend for your thread to
continue doing some other work after calling BeginReceive.

Third, I finally noticed a bug in your call to Receive, in which you fail to
update the buffer offset. I don't think this would cause the issue you're
asking about, but it's a serious problem.


Here's how I'd try to write it (note of course that not having used sockets
in .NET, I can't guarantee this is perfectly correct ):

public static byte[] Receive(Socket openSocket, int length)
{
byte[] buffer = new byte[length];
int totalreceive = 0;

do
{
int lastreceive;

/*
* For non-blocking sockets, the Socket.Select method will block
* the thread until there is actually data to be read from the
socket.
*
* If you want to get really picky, check to make sure your socket
* is still in the socklistRead list before trying to read from it.
* Since it's the only one that was in there to begin with, it still
* should be and even if it's not the worst that can happen is we
* loop back around and try again.
*/
if (!openSocket.Blocking)
{
ArrayList socklistRead = new ArrayList();

socklistRead.Add(openSocket);
Socket.Select(socklistRead, null, null, -1);
}

/* Be prepared for an exception */
try
{
/*
* For blocking socket, this will block the thread until
* data is available. For a non-blocking socket, we hope
* that the data is still there after returning from
* Socket.Select, but it's no big deal if it's not (we'll
* get a WSAEWOULDBLOCK error and go back to try again).
*/
lastreceive = openSocket.Receive(buffer, totalreceive, length,
SocketFlags.None);

/*
* Sockets will return zero if the socket is
* closed and we've already read all the data on the socket
*/
if (lastreceive == 0)
{
throw new Exception("Socket was closed");
}
}
catch (SocketException exc)
{
/*
* WSAEWOULDBLOCK is a non-fatal error...we just need to
* go back and try again.
*/
if (exc.ErrorCode != WSAEWOULDBLOCK)
{
throw;
}
lastreceive = 0;
}
catch
{
throw;
}

/*
* At this point, we've received valid data, and it's been
* put into the buffer. Update our byte counter to reflect
* that.
*/
totalreceive += lastreceive;
length -= lastreceive;
} while (length > 0);
}

By the way, there is a Socket.Receive overload that takes an "out ErrorCode"
parameter. The docs claim that even this method returns an exception in the
case of a Winsock error, but I suspect that in reality the function returns
SOCKET_ERROR (-1) and sets the output parameter (this would be consistent
with how Winsock itself works). I didn't bother to try it to see, since
other exceptions can still happen anyway, but if it's true that you can
detect WSAEWOULDBLOCK that way instead, it might be nicer to use that
instead of having to use a try/catch block within the loop. Instead of:

try
{...}
catch (SocketException...)
{...}
catch
{...}

You'd have something like this:

lastreceive = openSocket.Receive(..., err);
if (lastreceive == SOCKET_ERROR)
{
if (err != WSAEWOULDBLOCK)
{
throw new SocketException(err);
}

lastreceive = 0;
}
else if (lastreceive == 0)
{
throw new Exception("Socket was closed");
}

Note the extensive use of ellipsis' to denote code I didn't want to bother
typing out.

Anyway, I hope this helps. I'm making the (possibly incorrect) assumption
that the .NET version of sockets doesn't stray too far from the underlying
functionality. I essentially translated what I do know to be correct for
Winsock generally into the means and methods available in .NET. With some
luck, it'll be exactly what you need.

Pete


 
Reply With Quote
 
Daniel
Guest
Posts: n/a
 
      16th Sep 2006
Hey Sem

Since i have implemented what you are doing successfully and did in fact get
it right that you are 'losing' bytes i will continue to try and help.

the reason i believe you are losing data is the exact reason that i was when
i first attempted this.

Ok imagine this, you send a total of 800 bytes, and your buffer is 500 bytes
in size (500 for arguments sake to keep numbers easy)

Your async socket listens and receives 500 bytes (your total buffer size
with still 300 to come), you read the full buffer and then finish. Now the
next 300 comes through and so you receive 300 bytes.

So your second receive is a 500 byte buffer with only 300 byes of data in
it.

So when you hit the 300th byte of that 500 check your code and see if at
this point you stop reading, as after all you have your data, and break. If
so you just lost 200 bytes. Sure that 200 bytes may be empty but it might
not. If another send was done at the other end it may have been joined on
the end. and your break just ignored it.

So this is what you must remember:

1) Send 4 bytes containing the ength of the data being sent
2) receiveing end, read first 4 bytes and store size of data to come
3) read that many bytes and use the end of those bytes not as a point to
break and say end of transmission but end of that object being received and
now...
4) ....now the next 4 bytes check for size again and so on ans so on

So to clarfiy further. Imagine sending an object of 1024 bytes in size. We
would do this

a) create 4 bytes containing the length of the data being sent, the number
1024
b) send the 4 bytes
c) send the data
d) receive and
1)first receive check first 4 bytes to get size expected
2) read that many bytes
3) on reading that many bytes check next 4 bytes received for expected
size of next data comin thorugh
4) if expected size now is 0 then no more to come, go back to active
waiting state
5) if not 0 then read as usual and so on


Does that make sense?





"semedao" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi , I take back my words about missing data... )
> ok ok , the data is missing , but , help me understand
> why ??
> firsy - yes , I am using TCP
> now , If I made loop around the "beginRecv until it will return the
> expected buffer length , the app is in infinite loop in case when the
> return of endrecv is zero.
> so , how can I handle it ?
>
> "Peter Duniho" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> "Daniel" <(E-Mail Removed)> wrote in message
>> news:%(E-Mail Removed)...
>>> I didn't read all of Peters reply but he did mention the delay fixing
>>> it. Also you said 'no' to my comment that your 'losing data.
>>>
>>> Well if when you debug you receive 5 bytes and when you don't debug you
>>> don't recive 5 bytes....haven't you lost data?

>>
>> Not necessarily. All we know is that he doesn't receive the data when he
>> expected to. Since he has no loop around his receive attempt, he
>> definitely will fail to read the data if it's not read the first time
>> through. But the data remains on the socket, until such time as it IS
>> read or the socket is closed. It's entirely possible that his code does
>> eventually read the data, preventing it from being lost.
>>
>> I'd say if he says he doesn't lose data, we should take his word for it,
>> at least for the moment.
>>
>> In addition...
>>
>>> the fatc you reminded me you are using async sockets makes me think your
>>> new to it.
>>>
>>> I have written commerical software using async sockets in .net 2.0 and
>>> when i was learning i had the exact same problem,.
>>>
>>> What i didn't know at the time was a few key things:
>>>
>>> 1) data will never go out of order
>>> 2) you will never lose bytes
>>> 3) you may receive all your data in one stream call
>>>
>>> So say you sent 10 bytes, then 5 bytes then 5 more bytes
>>>
>>> Your endreceive may return : 20bytes.......it may return 10, then 5 then
>>> 5...(as in when there is a delay due to debugging), or it may return 15
>>> then 5.

>>
>> All true. However, the thing that many programmers miss (and which you
>> didn't mention) is that you may not even receive 10 bytes or 5 bytes or
>> any given number of bytes for any given call to receive.
>>
>> In your example, the sender sends 20 bytes. The receiver may in fact
>> wind up receiving 1 byte at a time, 20 times, and the code must be
>> prepared to deal with this. In reality, the extreme cases almost never
>> happen (eg getting just one byte at a time) but the API specification
>> doesn't guarantee anything better than that, and if your code isn't
>> handling that degenerate case, it likely also doesn't handle the more
>> likely cases as well.
>>
>> With a stream-oriented socket (eg TCP), there are no message boundaries.
>> The way the data is grouped during the send has nothing to do with the
>> way the data is grouped during the receive.
>>
>> Now, as it happens, we don't really know whether the original poster is
>> using a stream-oriented socket. I didn't see anything in his post or
>> code that implies TCP (or similar protocol). If he's using UDP, all of
>> the above isn't relevant and there's a whole different set of
>> considerations (ie, one receive always returns exactly what one send
>> sent, but you may receive the same datagram more than once, not at all,
>> or out of order from the other datagrams).
>>
>> The real issue here appears to be what "blocking" and "non-blocking" mean
>> with respect to the .NET implementation of sockets. I suspect that even
>> though the documentation says otherwise, the EndReceive method only
>> blocks until the receive is completed when a blocking socket is used (and
>> of course, as you point out, for a TCP socket "complete" does not
>> necessary mean "the buffer has been filled"...it just means *some* data
>> has been received).
>>
>> Pete
>>

>
>



 
Reply With Quote
 
William Stacey [MVP]
Guest
Posts: n/a
 
      16th Sep 2006
Not sure what is wrong with your code, but here is some that should work for
you.

public delegate void GetBytesDelegate(byte[] buf, Exception ex);
public static void GetBytes(Socket s, int length, GetBytesDelegate
callback)
{
if (length < 1)
throw new ArgumentOutOfRangeException("length");

byte[] buffer = new byte[length];
int bytesRead = 0;

AsyncCallback cb = null;
cb = delegate(IAsyncResult ar)
{
try
{
int read = s.EndReceive(ar);
if (read == 0)
{
callback(null, null); // Peer closed send.
return;
}

bytesRead += read;

if (bytesRead == length)
callback(buffer, null); // Done.
else // Else, need more data.
s.BeginReceive(buffer, bytesRead, length -
bytesRead, SocketFlags.None, cb, null);
}
catch (Exception ex)
{
callback(buffer, ex);
}
};

s.BeginReceive(buffer, bytesRead, length - bytesRead,
SocketFlags.None, cb, null);
}

--
William Stacey [MVP]

"semedao" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
| Hi , I am using asyc sockets p2p connection between 2 clients.
| when I debug step by step the both sides , i'ts work ok.
| when I run it , in somepoint (same location in the code)
| when I want to receive 5 bytes buffer , I call the BeginReceive and then
| wait on AsyncWaitHandle.WaitOne()
| but it is signald imidiatly , and the next call to EndReceive return zero
| bytes length , also the buffer is empty.
| here is the code:
| public static byte[] Receive(Socket OpenSocket, int length)
|
| {
|
| byte[] buffer = new byte[length];
|
| int totalreceive = 0;
|
| int _lastReceive = 0;
|
| if (OpenSocket.Blocking)
|
| totalreceive = OpenSocket.Receive(buffer);
|
| else
|
| {
|
| IAsyncResult ar;
|
| do
|
| {
|
| //in this point the OpenSocket.Available == 0 !
|
| ar = OpenSocket.BeginReceive(buffer, 0, length, SocketFlags.None, null,
| null);
|
| ar.AsyncWaitHandle.WaitOne(); // something "signald it before data
received?
|
| _lastReceive = OpenSocket.EndReceive(ar);
|
| if (_lastReceive == 0) // happen when run the code , doeas not happen if
| step by step slowly!
|
| {
|
| buffer = null;
|
| throw new Exception("No data receive");
|
| }
|
| totalreceive += _lastReceive;
|
| } while (totalreceive < length);
|
| }
|
| return buffer;
|
| }
|
| what is my problem ? I don't want to use sync calls because the rest of
the
| session is async also , so I only want to makethe async - sinc like
forthis
| part ofthe code , also , when in the debug mode I change the
| OpenSocket.Blocking to True - cause it to call sync receive instead of
| beginrecv , also return with zero length buffer
|
|
|
| any ideas ?
|
|


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Step from VB6 to .Net (COM) in Debug Mode? Terry Microsoft VB .NET 2 15th Aug 2008 10:13 PM
Debug/Step mode in macro/VBA Jim Microsoft Access VBA Modules 3 30th Jul 2008 04:02 PM
step out and step in do not show on the Visual studio 2005 debug m =?Utf-8?B?bWFydGluMQ==?= Microsoft VB .NET 0 30th Aug 2007 08:56 PM
Macro Works but not in Debug Step mode Bob Smedley Microsoft Excel Programming 3 31st Jan 2006 04:28 PM
Debug Step vs Run Mode Arthur Microsoft Excel Programming 3 9th Nov 2003 05:03 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:39 AM.