#if NET_2_0
using System.Collections.Generic;
-using System.Timers;
#if !NET_2_1
using System.Net.NetworkInformation;
#endif
* their name without also updating the runtime code.
*/
private static int ipv4Supported = -1, ipv6Supported = -1;
+ int linger_timeout;
static Socket ()
{
}
}
+ void Linger (IntPtr handle)
+ {
+ if (linger_timeout <= 0 || !connected)
+ return;
+
+ // We don't want to receive any more data
+ int error;
+ Shutdown_internal (handle, SocketShutdown.Receive, out error);
+ if (error != 0)
+ return;
+
+ int seconds = linger_timeout / 1000;
+ int ms = linger_timeout % 1000;
+ if (ms > 0) {
+ // If the other end closes, this will return 'true' with 'Available' == 0
+ Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
+ if (error != 0)
+ return;
+
+ }
+ if (seconds > 0) {
+ LingerOption linger = new LingerOption (true, seconds);
+ SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
+ /* Not needed, we're closing upon return */
+ /*if (error != 0)
+ return; */
+ }
+ }
+
protected virtual void Dispose (bool explicitDisposing)
{
if (disposed)
closed = true;
IntPtr x = socket;
socket = (IntPtr) (-1);
+ Linger (x);
+ //DateTime start = DateTime.UtcNow;
Close_internal (x, out error);
+ //Console.WriteLine ("Time spent in Close_internal: {0}ms", (DateTime.UtcNow - start).TotalMilliseconds);
if (blocking_thread != null) {
blocking_thread.Abort ();
blocking_thread = null;
public void Close ()
{
+ linger_timeout = 0;
((IDisposable) this).Dispose ();
}
#if NET_2_0
public void Close (int timeout)
{
- System.Timers.Timer close_timer = new System.Timers.Timer ();
- close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
- close_timer.Interval = timeout * 1000;
- close_timer.AutoReset = false;
- close_timer.Enabled = true;
- }
-
- private void OnTimeoutClose (object source, ElapsedEventArgs e)
- {
- this.Close ();
+ linger_timeout = timeout;
+ ((IDisposable) this).Dispose ();
}
#endif
return true;
}
#endif
-#if !NET_2_1
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
+#if !NET_2_1
/* This overload is needed as the async Connect method
* also needs to check the socket error status, but
* getsockopt(..., SO_ERROR) clears the error.