C# Socket ReceiveAsync
Ok I went and took a large buffer and send it in batches with a sleep interval in between to replicate 'not all bytes received' So my code above doesn't recieve all bytes. for those who also use ReceiveAsync(..) here is my code that works
private byte[] ReadBySize(int size = 4)
{
var readEvent = new AutoResetEvent(false);
var buffer = new byte[size]; //Receive buffer
var totalRecieved = 0;
do
{
var recieveArgs = new SocketAsyncEventArgs()
{
UserToken = readEvent
};
recieveArgs.SetBuffer(buffer, totalRecieved, size - totalRecieved);//Receive bytes from x to total - x, x is the number of bytes already recieved
recieveArgs.Completed += recieveArgs_Completed;
_connecter.ReceiveAsync(recieveArgs);
readEvent.WaitOne();//Wait for recieve
if (recieveArgs.BytesTransferred == 0)//If now bytes are recieved then there is an error
{
if (recieveArgs.SocketError != SocketError.Success)
throw new ReadException(ReadExceptionCode.UnexpectedDisconnect,"Unexpected Disconnect");
throw new ReadException(ReadExceptionCode.DisconnectGracefully);
}
totalRecieved += recieveArgs.BytesTransferred;
} while (totalRecieved != size);//Check if all bytes has been received
return buffer;
}
void recieveArgs_Completed(object sender, SocketAsyncEventArgs e)
{
var are = (AutoResetEvent)e.UserToken;
are.Set();
}
The way I work with my Socket applications is to send a Buffer that consist of some variables
[0] -> 0,1,2 0 is keep alive, 1 means there are data, 2 means a type off error occured
[1,2,3,4] size of the actual buffer I am sending
[x(size of 1,2,3,4)] the actual 'Serialized' data buffer
Related videos on Youtube
Donald Jansen
I am a very down to earth kind of guy who loves to work with people. My hobbies (apart from developing) is playing games, playing airsoft or going out with my girlfriend In the development world I love to work with C# and C++
Updated on June 06, 2022Comments
-
Donald Jansen almost 2 years
I am used to sync sockets and had a few headaches to get to the point where I am now, especially with
Socket.Receive(..)
not always receiveing all bytesHere is my code what I used to use
public byte[] Receive(int size) { var buffer = new byte[size]; var r = 0; do { // ReSharper disable once InconsistentlySynchronizedField var c = _clientSocket.Receive(buffer, r, size - r, SocketFlags.None); if (c == 0) { throw new SocketExtendedException(); } r += c; } while (r != buffer.Length); return buffer; }
Now I started to use sockets in Windows Phone BUT
.Receive(..)
is not available and I managed to getSocket.ReceiveAsync(..)
working but I am concerned (no problems happened so far) here is my new code, I have not implemented the checking if all bytes has been recieved or not nor do I know if I have to with the following codeprivate byte[] ReadBySize(int size = 4) { var readEvent = new AutoResetEvent(false); var buffer = new byte[size]; var recieveArgs = new SocketAsyncEventArgs() { UserToken = readEvent }; recieveArgs.SetBuffer(buffer, 0, size); recieveArgs.Completed += recieveArgs_Completed; _connecter.ReceiveAsync(recieveArgs); readEvent.WaitOne(); if (recieveArgs.BytesTransferred == 0) { if (recieveArgs.SocketError != SocketError.Success) throw new SocketException((int)recieveArgs.SocketError); throw new CommunicationException(); } return buffer; } void recieveArgs_Completed(object sender, SocketAsyncEventArgs e) { var are = (AutoResetEvent)e.UserToken; are.Set(); }
This is my first use of
ReceiveAsync
can someone point out anything I might have done wrong or need to change-
Donald Jansen over 8 yearsIn windows Phone BeginRecieve and Recieve is not available, I have used BeginReceive aswell but its not available, I can only use StreamSocket or Socket (with RecieveAsync)
-
Bauss over 8 yearsYeah sorry my bad, did not read it was windows phone.
-
Luaan over 8 yearsAre you using TCP? Have you considered using
TcpClient
/TcpListener
if that is the case?NetworkStream
is a lot easier to work with.
-
-
Seng Cheong about 7 yearsWhy are you even using async APIs if you're effectively making them synchronous by calling
ReceiveAsync
thenWaitOne
in the same thread? You could just call the synchronous, blockingReceive()
. -
Donald Jansen about 7 yearsBecause this was 2 years ago and it was windows phone, windows phone does not have Recieve() if you've read the question you would have seen that. I needed it synchronous at that time. Today the code looks a lot different
-
Seng Cheong about 7 yearsThank you, I did indeed miss that part. I would have never guessed that the sync api would be unavailable.
-
Donald Jansen about 7 years:) My code now contains
TaskCompletionSource<byte[]>()
, getting rid of the uglyAutoResetEvent
and I now make use ofasync/await
,byte[]
has becomeTask<byte[]>
andreturn buffer
has becomereturn tcs.Task;
,recieveArgs_Completed
also changed to accomodate TaskCompletionSource -
Dominic Jonas about 5 years@DonaldJansen could you update your answer to your latest comment? Would be great to see an
async/await
implementation! 😊