I recently tackled the weird behavior of the synchronous .Net receive method. I needed to write an application that has nodes that communicate with each other, sending / receiving data. Each server has a receive loop that is synchronous, after receiving a serialized class, it deserializes and processes it. After that, it asynchronously passes this serialized class to some selected nodes (using AsynchSendTo).
MSDN clearly states that:
"If you use a socket-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer. If the remote host disconnects the Socket connection with the shutdown method and all available data, the receive method will end immediately and return zero bytes."
In my case, this is not the case. There are some random cases when Receive does not block and returns 0 bytes (without a deterministic situation) immediately after the connection is established. I am 100% sure that the sender sent up to 1000 bytes. Another fun fact: when you install Sleep (500), before everything works out, everything works fine. The following is the reception code:
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { _listener.Bind(_serverEndpoint); _listener.Listen(Int32.MaxValue); while (true) { Console.WriteLine("Waiting for connection..."); Socket handler = _listener.Accept(); int totalBytes = 0; int bytesRec; var bytes = new byte[DATAGRAM_BUFFER]; do {
Also sending part:
public void AsynchSendTo(Datagram datagram, IPEndPoint recipient) { byte[] byteDatagram = SerializeDatagram(datagram); try { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.BeginConnect(recipient, ConnectCallback, new StateObject(byteDatagram, byteDatagram.Length, socket)); } catch (SocketException e) { Console.WriteLine(e); } } public void ConnectCallback(IAsyncResult result) { try { var stateObject = (StateObject)result.AsyncState; var socket = stateObject.Socket; socket.EndConnect(result); socket.BeginSend(stateObject.Data, 0, stateObject.Data.Length, 0, new AsyncCallback(SendCallback), socket); } catch (Exception ex) { Console.WriteLine("catched!" + ex.ToString()); } } public void SendCallback(IAsyncResult result) { try { var client = (Socket)result.AsyncState; client.EndSend(result); client.Shutdown(SocketShutdown.Both); client.Close(); } catch (Exception ex) { Console.WriteLine(ex); } } class StateObject { public Byte[] Data { get; set; } public int Size; public Socket Socket; }
My question is: am I using synchronous reception incorrectly? Why doesnโt it block the event, although there is data to receive?