NETCF Async TCP socket graceful closing problem

I have a client / server TCP application to communicate with a Windows CE device through an ActiveSync connection. Both the client and server use asynchronous sockets (i.e., the Socket.Begin* and Socket.End* ). When the client and server are running on my desktop, everything works exactly as expected, but when the client is running on a Windows CE device connected via ActiveSync, I always get a SocketException in ReceiveCallback after calling Socket.Shutdown (when the device initiates disconnection). Full exception:

 System.Net.Sockets.SocketException: An error message cannot be displayed because an optional resource assembly containing it cannot be found at System.Net.Sockets.Socket.ReceiveNoCheck() at ReceiveAsyncRequest.doRequest() at AsyncRequest.handleRequest() at WorkerThread.doWork() at WorkerThread.doWorkI() at WorkItem.doWork() at System.Threading.Timer.ring() 

Everything also works correctly if the server (running on the desktop) initiates a shutdown. I have a couple of ideas on how to avoid this, including banning disconnected devices and ignoring all exceptions after initiating a disconnection. However, I would like to know why this is happening, and if there is a better way to handle this.

Disable ReceiveCallbacks (operatively identical both on the server and on the client):

 public bool Disconnect(StateObject state) { try{ if(state.isDisconnecting) return false; state.isDisconnecting = true; state.sock.Shutdown(SocketShutdown.Both); //Wait for sending and receiving to complete, but don't wait more than 10 seconds for(int i=0; i<100 && (state.isSending || state.isReceiving); i++){ System.Threading.Thread.Sleep(100); } /* Log the disconnect */ state.sock.Close(); return true; } catch (Exception e){ /* Log the exception */ return false; } } private void ReceiveCallback(IAsyncResult iar) { StateObject state = (StateObject)iar.AsyncState; try{ //handle the new bytes in the buffer. int recv = state.sock.EndReceive(iar); //Handle the buffer, storing it somewhere and verifying complete messages. if(recv > 0){ //start listening for the next message state.sock.BeginReceive(state.recvBuffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } else { state.isReceiving = false; Disconnect(state); } } catch (Exception e){ /* Log the exception */ } } //For reference, A StateObject looks kinda like this: public class StateObject { public const int BUFFER_SIZE = 1024; public Socket sock = null; public bool isSending = false; public bool isReceiving = false; public bool isDisconnecting = false; public byte[] recvBuffer = new byte[BUFFER_SIZE]; public byte[] sendBuffer = new byte[BUFFER_SIZE]; //Other stuff that helps handle the buffers and ensure complete messages, // even when TCP breaks up packets. } 
+4
source share
2 answers

To get the actual exception, try to figure out which library he needs and deploy?

0
source

If the message connot is displayed on your device because the message is not installed on your device. You must install netcf.messages.cab. You will find it here:

 C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE\Diagnostics 

After installing this CAB file, run the application again and post a new error.

0
source

Source: https://habr.com/ru/post/1347765/


All Articles