J'ai une application client/serveur TCP pour communiquer avec un périphérique Windows CE via une connexion ActiveSync. Le client et le serveur utilisent tous les deux des sockets asynchrones (c'est-à-dire les fonctions Socket.Begin*
et Socket.End*
). Lorsque le client et le serveur s'exécutent sur mon bureau, tout fonctionne exactement comme prévu, mais lorsque le client s'exécute sur le périphérique Windows CE connecté via ActiveSync, j'obtiens toujours un SocketException
sur ReceiveCallback après avoir appelé Socket.Shutdown
(lorsque le périphérique démarre) la déconnexion). L'exception est pleine:Problème d'arrêt progressif du socket TCP Async .NETCF
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()
Tout semble également fonctionner correctement si le serveur (en cours d'exécution sur le bureau) déclenche la déconnexion. J'ai quelques idées sur la façon d'éviter cela, y compris interdisant les déconnexions initiées par le périphérique et ignorer toutes les exceptions après avoir initié une déconnexion. Cependant, j'aimerais savoir pourquoi cela se produit et s'il y a une meilleure façon de le gérer.
La déconnexion et ReceiveCallbacks (identique sur le plan opérationnel sur le serveur et le client) sont:
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.
}
Ne supposez jamais que le CF et le framework complet se comporteront de manière identique. http://blog.opennetcf.com/ctacke/2008/10/02/BehavioralDifferencesBetweenTheCFAndFFx.aspx – ctacke
@ctacke, ouais, je commence vraiment à comprendre ça, aussi pénible que ça ... – chezy525
as-tu le exception lors du débogage? (existe-t-il un débogueur distant pour WinCE?) existe-t-il une InnerException avec plus de détails? – user1859022