2010-07-14 4 views
3

J'ai un problème sérieux avec la méthode de réception asynchrone de System.Net.Sockets.Socket.C#: AsyncCallback n'est pas appelé sur Socket.BeginReceive

Voici le code que j'utilise pour ouvrir la connexion:

_socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 
_socket.Connect(endpoint); 

byte[] buffer = new byte[1024]; 
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, buffer); 

et est ici la méthode de rappel:

private void ReceiveCallback(IAsyncResult result) 
{ 
    byte[] buffer = (byte[])result.AsyncState; 
    int count = _socket.EndReceive(result); 

    if (count > 0) 
    { 
      // Do something 
    } 

    buffer = new byte[1024]; 
    _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, buffer); 
} 

Le problème est que le ReceiveCallback est jamais appelé, malgré la prise être connecté.

Quelqu'un peut-il m'aider sur celui-ci?

+1

Etes-vous sûr qu'il y a des données envoyées à la socket? La méthode de rappel n'est pas appelée avant la réception des données. ('count' ne sera jamais' 0'.) – dtb

+0

Ok, si les données sont envoyées, le callback est appelé, la documentation de msdn était un peu trompeuse indiquant: "La méthode EndReceive bloquera jusqu'à ce que les données soient disponibles" c'est vrai, mais Si le rappel n'est pas appelé, EndReceive n'est ni: /. Comment puis-je détecter une interruption de la connexion alors? – haze4real

+0

Si vous appelez EndReceive avant que les données ne soient disponibles, EndReceive se bloque jusqu'à ce que les données soient disponibles. Mais, puisque le rappel n'est appelé que lorsque les données sont disponibles, vous n'appelez jamais EndReceive avant que les données ne soient disponibles. Vous pouvez détecter une interruption de la connexion uniquement en envoyant * des données (qui échoueront si la connexion a été interrompue). – dtb

Répondre

3

Tout d'abord, n'ignorez pas si EndRecieve renvoie 0 octet. Cela signifie que la connexion a été fermée par le point final distant. Etes-vous sûr que l'extrémité distante vous a envoyé quelque chose? Mon pari est que ce n'est pas le cas.

J'ai fait un certain nombre d'applications de socket et j'ai jamais avait des problèmes avec le rappel n'est pas appelé.

Il est également très important de gérer les exceptions dans les méthodes de rappel. Ne pas le faire provoquera le plantage de votre application lorsqu'une exception est levée.

+0

le code dans ma question était seulement un exemple de code pour reproduire le problème, je gère toujours les exceptions à l'intérieur du rappel ainsi que la gestion de CompletedSynchronously. Merci pour l'explication concernant 0 octets :) – haze4real