2011-05-12 6 views
6

Tengo un código que usa un socket asíncrono para enviar un mensaje al cliente y esperar respuesta de él. Si el cliente no respondió en un interno especificado, considerará el tiempo de espera. Algunos de los artículos en Internet sugieren usar WaitOne, pero esto bloqueará el hilo y difiere el propósito de utilizar la finalización de E/S.¿Cómo manejar el tiempo de espera en Async Socket?

¿Cuál es la mejor manera de manejar el tiempo de espera en el socket asíncrono?

Sub OnSend(ByVal ar As IAsyncResult) 
     Dim socket As Socket = CType(ar.AsyncState ,Socket) 
     socket.EndSend(ar) 

     socket.BeginReceive(Me.ReceiveBuffer, 0, Me.ReceiveBuffer.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), socket) 

End Sub 

Respuesta

6

No puede salir del tiempo de espera o cancelar las operaciones asincrónicas Socket.

Todo lo que se puede hacer es iniciar su propio Timer que cierra la Socket -la devolución de llamada a continuación, se llama inmediatamente y la función EndX va a volver con un ObjectDisposedException si usted lo llama. Aquí hay un ejemplo:

using System; 
using System.Threading; 
using System.Net.Sockets; 

class AsyncClass 
{ 
    Socket sock; 
    Timer timer; 
    byte[] buffer; 
    int timeoutflag; 

    public AsyncClass() 
    { 
      sock = new Socket(AddressFamily.InterNetwork, 
       SocketType.Stream, 
       ProtocolType.Tcp); 

      buffer = new byte[256]; 
    } 

    public void StartReceive() 
    { 
      IAsyncResult res = sock.BeginReceive(buffer, 0, buffer.Length, 
       SocketFlags.None, OnReceive, null); 

      if(!res.IsCompleted) 
      { 
       timer = new Timer(OnTimer, null, 1000, Timeout.Infinite); 
      } 
    } 

    void OnReceive(IAsyncResult res) 
    { 
      if(Interlocked.CompareExchange(ref timeoutflag, 1, 0) != 0) 
      { 
       // the flag was set elsewhere, so return immediately. 
       return; 
      } 

      // we set the flag to 1, indicating it was completed. 

      if(timer != null) 
      { 
       // stop the timer from firing. 
       timer.Dispose(); 
      } 

      // process the read. 

      int len = sock.EndReceive(res); 
    } 

    void OnTimer(object obj) 
    { 
      if(Interlocked.CompareExchange(ref timeoutflag, 2, 0) != 0) 
      { 
       // the flag was set elsewhere, so return immediately. 
       return; 
      } 

      // we set the flag to 2, indicating a timeout was hit. 

      timer.Dispose(); 
      sock.Close(); // closing the Socket cancels the async operation. 
    } 
} 
+1

Encontré una respuesta similar. http://stackoverflow.com/questions/1231816/net-async-socket-timeout-check-thread-safety. La idea es tener un solo temporizador para controlar toda la conexión existente para verificar si se ha agotado el tiempo de espera. – kevin

Cuestiones relacionadas