Detecting Remote Client Socket Close in BeginReceive

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • O.B.

    #1

    Detecting Remote Client Socket Close in BeginReceive

    In the following code snippet, the thread successfully makes it to the
    line where it waits for data to be received. Then the client closes the
    connection. The thread wakes up and returns from the WaitOne()
    operation. No exception is thrown when it loops and executes
    BeginReceive() again. The WaitOne() operation returns immediately.
    Thus, there's an endless loop.

    How does one detect that the remote client has closed the connection in
    this situation?


    //
    // Started as a new thread to handle data received on an
    // open socket.
    //
    private void ReceiveDataEven tLoop(Socket clientSocket) {
    while (true) {
    try {
    ClientState clientState = new ClientState(cli entSocket);
    IAsyncResult result = clientSocket.Be ginReceive(
    clientState.Buf fer,
    0,
    clientState.Buf fer.Length,
    SocketFlags.Non e,
    new AsyncCallback(t his.ReceiveData Callback),
    clientState);

    // Wait for the EndReceive before issuing a new BeginReceive
    // When the remote client closes the connection, this starts
    // to return immediately. How to identify that remote client
    // closed connection?
    result.AsyncWai tHandle.WaitOne ();

    } catch (SocketExceptio n) {
    removeSocket(cl ientSocket);
    break;
    } catch (Exception) {
    removeSocket(cl ientSocket);
    break;
    }
    }
    }

  • O.B.

    #2
    Re: Detecting Remote Client Socket Close in BeginReceive

    OK. I have a workaround:

    Instead of using "result.AsyncWa itHandle.WaitOn e()", I created a
    ManualResetEven t and passed it to the BeginReceive delegate. When the
    BeginReceive delegate starts, it gets the number of bytes when it calls
    EndReceive. If 0, the BeginReceive delegate closes the socket. After
    processing the data, the ManualResetEven t is set. Thus, when the
    ReceiveDataEven tLoop wakes up, it will try to access a disposed object
    when it calls BeginReceive and then exit from its event loop.



    O.B. wrote:
    In the following code snippet, the thread successfully makes it to the
    line where it waits for data to be received. Then the client closes the
    connection. The thread wakes up and returns from the WaitOne()
    operation. No exception is thrown when it loops and executes
    BeginReceive() again. The WaitOne() operation returns immediately.
    Thus, there's an endless loop.
    >
    How does one detect that the remote client has closed the connection in
    this situation?
    >
    >
    //
    // Started as a new thread to handle data received on an
    // open socket.
    //
    private void ReceiveDataEven tLoop(Socket clientSocket) {
    while (true) {
    try {
    ClientState clientState = new ClientState(cli entSocket);
    IAsyncResult result = clientSocket.Be ginReceive(
    clientState.Buf fer,
    0,
    clientState.Buf fer.Length,
    SocketFlags.Non e,
    new AsyncCallback(t his.ReceiveData Callback),
    clientState);
    >
    // Wait for the EndReceive before issuing a new BeginReceive
    // When the remote client closes the connection, this starts
    // to return immediately. How to identify that remote client
    // closed connection?
    result.AsyncWai tHandle.WaitOne ();
    >
    } catch (SocketExceptio n) {
    removeSocket(cl ientSocket);
    break;
    } catch (Exception) {
    removeSocket(cl ientSocket);
    break;
    }
    }
    }
    >

    Comment

    • Peter Duniho

      #3
      Re: Detecting Remote Client Socket Close in BeginReceive

      "O.B." <funkjunk@bells outh.netwrote in message
      news:12k24tvgck b8c0b@corp.supe rnews.com...
      [...]
      How does one detect that the remote client has closed the connection in
      this situation?
      As you have found, the receive function returns a bytes received value of 0
      when the connection is closed.

      However, your problem has less to do with that, than that you have created
      an infinite loop that tries to receive over and over again without any means
      of checking the socket for validity.

      It seems to me that if you insist on this design, then the BeginReceive
      method *ought* to throw an exception once your socket has been closed. That
      is, after receiving 0 for the return value for EndReceive, you ought to be
      able to just close the socket there, causing an exception here and allowing
      the loop to exit.

      However, in that case you don't have a direct means of knowing whether the
      connection was closed normally or abnormally. IMHO, it would be better to
      not have this design in the first place, requeuing the receive *only* when
      you know you have successfully completed the previous receive (that is, in
      the same code where you call EndReceive).

      Pete


      Comment

      Working...