Does Socket.Shutdown or Socket.Close Block and when?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Tanger

    Does Socket.Shutdown or Socket.Close Block and when?


    Context:
    C#
    System.Net.Sock ets
    Socket created with constructor prarmeters Internetwork, Stream and TCP
    everything else is left at the default parameters and options except linger
    may be changed as I find appropriate.
    I am using the socket asynchronously by calling the BeingSend and
    BeginReceive calls. I would like to be able to call shutdown and close
    asynchronously if possible.


    As far as I understand from the MSDN documentation calling
    Socket.Shutdown on a socket will ensure that all data in the send buffer will
    get sent to the remote host before the socket is closed. I also understand
    that the linger socket option can be used to set how long the socket will try
    to send any data in the send buffer before giving up and closing the socket.
    The MSDN documentation for Socket.Close states:
    If you need to call Close without first calling Shutdown, you can ensure
    that data queued for outgoing transmission will be sent by setting the
    DontLinger Socket option to false and specifying a non-zero time-out
    interval. Close will then block until this data is sent or until the
    specified time-out expires.

    So it appears from the documentation excerpt that a call to Socket.Shutdown
    is not necessary as long as linger is enabled and set to the desired timeout
    before calling Socket.Close, is this true?
    My questions are these:

    *Does the linger option affect Socket.Shutdown in any way? If so, what way
    or ways?

    *Does Socket.Shutdown block while sending the data in the socket's send
    buffer or does it simply delegate the blocking to close?
    If so, where is the asynchronous method for Socket.Shutdown so I don't have
    to waste a thread just to babysit the shutdown.

    *If Socket.Close blocks while sending the remaining data in the send buffer
    (as indicated by the MSDN excerpt above) how can I call this asynchronously
    close a lingering socket without tying up a threadpool thread for 10 seconds
    or so (an eternity to be using a threadpool thread in a server application)?


    Thanks,

    --
    - Chris Tanger

  • Kevin Yu [MSFT]

    #2
    RE: Does Socket.Shutdown or Socket.Close Block and when?

    Hi Chris,

    First of all, I would like to confirm my understanding of your issue. From
    your description, I understand that you have several question on linger
    options and socket shutdown method. If there is any misunderstandin g,
    please feel free to let me know.

    As far as I know, Socket.Shutdown method waits until all the data in the
    buffer has been sent or received. However, if we only set linger options,
    the Socket will shutdown after certain timeout interval. So it is necessary
    to call Socket.Shutdown .

    I don't think linger option affects Socket.Shutdown , it affects close
    method.

    Socket.Shutdown blocks while sending the data in the socket's send buffer.
    There isn't asynchronous method for Socket.Shutdown in the .net framework
    class library. However, I think you can put the socket operations in a
    seperate thread from UI thread.

    Socket.Close also doesn't have asynchronous methods. You can also try to
    put all the socket operation in another thread.

    HTH.

    Kevin Yu
    =======
    "This posting is provided "AS IS" with no warranties, and confers no
    rights."

    Comment

    • Chris Tanger

      #3
      RE: Does Socket.Shutdown or Socket.Close Block and when?

      I was hoping for a more definitive answer, but no problem, I was just
      wondering if anyone knew for certain. Also, it is a bummer that Shutdown and
      Close cannot be called asynchronously. Here is why I wish to call them
      asynchronously without using an asynchronous delegate: I have a server that
      may have 1000 TCP connections coming into it. The server will expect to
      receive a heartbeat message every 5 seconds on each socket (to make sure the
      connection is still up to each client). If the server does not receive a
      heartbeat within say 10 seconds then the server will proceed to shutdown the
      socket. I wish to give the socket about 10 additional seconds to complete
      sending any data and to send a disconnect notification message if possible
      with the reason for the disconnect(hear tbeat timeout). Let us assume that
      the network path that carries all of these client-server connections goes
      down (a black hole down, so no nack packets are sent like when a firewall is
      blocking). The TCP connections will likely not throw an exception for
      20-120+ seconds. The server will notice that it has not received a heartbeat
      on each connection within the specified amount of time (10 seconds since the
      last heartbeat). The server will send a disconnect imminent message with the
      reason (heartbeat timeout) to each connection and then call shutdown on each
      connection. I want the server to attempt to send any remaining data in the
      socket send buffers for 10 seconds after shutdown is called. If it takes
      longer than 10 seconds I want the socket to perform a hard close and throw
      away any data in the send buffer. If all connections go down at the same
      time calling shutdown on a separate thread for each connection would require
      1000 threads. As you can imagine this is not a scalable solution. The
      threadpool cannot handle it, and I cannot reasonable start 1000 threads
      simultaneously for the task either.

      One solution that comes to mind is creating my own shutdown function that
      simply waits for 10 seconds after it is called using a System.Threadin g.Timer
      and then performs a hard close on the socket. The unfortunate thing about
      that particular solution is that the socket will not be closed immediately if
      the send buffer is empty or becomes empty before the elapsed timeout.

      So this is why I need to determine how these things work.

      I am going to write a test program that accepts incoming socket connections
      with at 8K receive buffer. The test program will never perform a read on the
      socket. There will be a corresponding test program that makes a connection
      to the listening program. It will have a 8K send buffer. The sending
      program will send 12k of data after connecting. This will cause the listing
      program's receive buffer to be completely filled to its 8K limit at which
      point the sending programs socket will get blocked leaving its 8K send buffer
      half full with 4K of data. Then I will call shutdown on the send programs
      socket and see what happens. I will also play around with the various linger
      options to determine how the Socket class behaves.

      I was posting to this group in the hopes that someone already knew the
      answer, but this program should enlighten me.

      One other question comes to mind, what if I set the Socket.Blocking = false?
      Will this result in Shutdown or close no longer blocking?

      Thanks,

      -Chris


      Comment

      • Chris Tanger

        #4
        RE: Does Socket.Shutdown or Socket.Close Block and when?


        OK, here are the results for anyone who is interested:
        I built and ran a program just as I said I would below. After
        experimenting a bit I found the following: Kevin Yu is correct
        Socket.Shutdown is unaffected by the LingerOption.
        Calling Socket.Shutdown does not block, also if Socket.Shutdown is first
        called, then subsequent calls to Socket.Close do not block either. The OS
        keeps trying to send the data in the send buffers of the socket until TCP
        times out (the timeout varies according to TCP algorithms and parameters).
        Enabling linger and setting the timeout to a certain number of seconds
        will cause a subsequent call to Socket.Close to block until either all data
        in the send buffer has been sent or the timeout has elapsed. If linger is
        disabled or Socket.Shutdown has been previously called then Socket.Close will
        not block.
        The disappointing part of all this is that I have no way to do a
        Socket.Shutdown with a timeout. In other words it would be nice to have a
        linger option for the Socket.Shutdown . That way I don't have a blocking
        problem and I also don't have a problem with sockets remaining open for too
        long and saping down system resources while hopelessly trying to send to a
        defunct client. If anyone knows how to do a socket.Shutdown type of
        operation with a timeout that initiates a hard close of the socket once
        elapsed.

        -Chris Tanger

        "Chris Tanger" wrote:
        [color=blue]
        > I was hoping for a more definitive answer, but no problem, I was just
        > wondering if anyone knew for certain. Also, it is a bummer that Shutdown and
        > Close cannot be called asynchronously. Here is why I wish to call them
        > asynchronously without using an asynchronous delegate: I have a server that
        > may have 1000 TCP connections coming into it. The server will expect to
        > receive a heartbeat message every 5 seconds on each socket (to make sure the
        > connection is still up to each client). If the server does not receive a
        > heartbeat within say 10 seconds then the server will proceed to shutdown the
        > socket. I wish to give the socket about 10 additional seconds to complete
        > sending any data and to send a disconnect notification message if possible
        > with the reason for the disconnect(hear tbeat timeout). Let us assume that
        > the network path that carries all of these client-server connections goes
        > down (a black hole down, so no nack packets are sent like when a firewall is
        > blocking). The TCP connections will likely not throw an exception for
        > 20-120+ seconds. The server will notice that it has not received a heartbeat
        > on each connection within the specified amount of time (10 seconds since the
        > last heartbeat). The server will send a disconnect imminent message with the
        > reason (heartbeat timeout) to each connection and then call shutdown on each
        > connection. I want the server to attempt to send any remaining data in the
        > socket send buffers for 10 seconds after shutdown is called. If it takes
        > longer than 10 seconds I want the socket to perform a hard close and throw
        > away any data in the send buffer. If all connections go down at the same
        > time calling shutdown on a separate thread for each connection would require
        > 1000 threads. As you can imagine this is not a scalable solution. The
        > threadpool cannot handle it, and I cannot reasonable start 1000 threads
        > simultaneously for the task either.
        >
        > One solution that comes to mind is creating my own shutdown function that
        > simply waits for 10 seconds after it is called using a System.Threadin g.Timer
        > and then performs a hard close on the socket. The unfortunate thing about
        > that particular solution is that the socket will not be closed immediately if
        > the send buffer is empty or becomes empty before the elapsed timeout.
        >
        > So this is why I need to determine how these things work.
        >
        > I am going to write a test program that accepts incoming socket connections
        > with at 8K receive buffer. The test program will never perform a read on the
        > socket. There will be a corresponding test program that makes a connection
        > to the listening program. It will have a 8K send buffer. The sending
        > program will send 12k of data after connecting. This will cause the listing
        > program's receive buffer to be completely filled to its 8K limit at which
        > point the sending programs socket will get blocked leaving its 8K send buffer
        > half full with 4K of data. Then I will call shutdown on the send programs
        > socket and see what happens. I will also play around with the various linger
        > options to determine how the Socket class behaves.
        >
        > I was posting to this group in the hopes that someone already knew the
        > answer, but this program should enlighten me.
        >
        > One other question comes to mind, what if I set the Socket.Blocking = false?
        > Will this result in Shutdown or close no longer blocking?
        >
        > Thanks,
        >
        > -Chris
        >
        >[/color]

        Comment

        • Kevin Yu [MSFT]

          #5
          RE: Does Socket.Shutdown or Socket.Close Block and when?

          Hi Chris,

          I think Socket.Blocking only affects on send and receive methods. While
          Shutdown will block by default.

          Kevin Yu
          =======
          "This posting is provided "AS IS" with no warranties, and confers no
          rights."

          Comment

          Working...