public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
{
- ThrowIfDisposedAndClosed ();
-
- int error;
int int_val = optionValue ? 1 : 0;
- SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
- if (error != 0) {
- if (error == (int) SocketError.InvalidArgument)
- throw new ArgumentException ();
- throw new SocketException (error);
- }
+ SetSocketOption (optionLevel, optionName, int_val);
}
public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
{
ThrowIfDisposedAndClosed ();
+ if (optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse ())
+ throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
+
int error;
SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
if (error != 0) {
+ if (error == (int) SocketError.InvalidArgument)
+ throw new ArgumentException ();
throw new SocketException (error);
}
}
s.Close ();
}
-#if MONOTOUCH
- // when the linker is enabled then reflection won't work and would throw an NRE
- // this is also always true for iOS - so we do not need to poke internals
- static bool SupportsPortReuse ()
- {
- return true;
- }
-#else
- static bool? supportsPortReuse;
- static bool SupportsPortReuse ()
- {
- if (supportsPortReuse.HasValue)
- return supportsPortReuse.Value;
-
- supportsPortReuse = (bool) typeof (Socket).GetMethod ("SupportsPortReuse",
- BindingFlags.Static | BindingFlags.NonPublic)
- .Invoke (null, new object [] {});
- return supportsPortReuse.Value;
- }
-#endif
-
// Test case for bug #31557
[Test]
public void TcpDoubleBind ()
SocketType.Stream, ProtocolType.Tcp))
using (Socket ss = new Socket (AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)) {
- s.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ var supportsReuseAddress = true;
+ try {
+ s.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ } catch (SocketException e) {
+ // Exception is thrown when ReuseAddress is not supported
+ supportsReuseAddress = false;
+ }
+
var ep = new IPEndPoint (IPAddress.Any, NetworkHelpers.FindFreePort ());
s.Bind (ep);
s.Listen(1);
- ss.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ if (supportsReuseAddress)
+ ss.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- Exception ex = null;
try {
ss.Bind (new IPEndPoint (IPAddress.Any, ep.Port));
ss.Listen(1);
+ if (!supportsReuseAddress)
+ Assert.Fail ("Reusing address is not supported, exception was expected on second bind.");
} catch (SocketException e) {
- ex = e;
}
-
- Assert.AreEqual (SupportsPortReuse (), ex == null);
}
}