diff --git a/websocket-sharp/Server/WebSocketServiceManager.cs b/websocket-sharp/Server/WebSocketServiceManager.cs
index 8dcd9ad9..ed511589 100644
--- a/websocket-sharp/Server/WebSocketServiceManager.cs
+++ b/websocket-sharp/Server/WebSocketServiceManager.cs
@@ -592,6 +592,67 @@ namespace WebSocketSharp.Server
return broadping (WebSocketFrame.CreatePingFrame (data, false).ToArray (), _waitTime);
}
+ ///
+ /// Removes a WebSocket service with the specified .
+ ///
+ ///
+ /// is converted to a URL-decoded string and
+ /// / is trimmed from the end of the converted string if any.
+ ///
+ ///
+ /// true if the service is successfully found and removed;
+ /// otherwise, false.
+ ///
+ ///
+ /// A that represents an absolute path to
+ /// the service to remove.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ ///
+ /// is empty.
+ ///
+ ///
+ /// -or-
+ ///
+ ///
+ /// is invalid.
+ ///
+ ///
+ public bool RemoveService (string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException ("path");
+
+ if (path.Length == 0)
+ throw new ArgumentException ("An empty string.", "path");
+
+ if (path[0] != '/')
+ throw new ArgumentException ("Not an absolute path.", "path");
+
+ if (path.IndexOfAny (new[] { '?', '#' }) > -1) {
+ var msg = "It includes either or both query and fragment components.";
+ throw new ArgumentException (msg, "path");
+ }
+
+ path = HttpUtility.UrlDecode (path).TrimSlashFromEnd ();
+
+ WebSocketServiceHost host;
+ lock (_sync) {
+ if (!_hosts.TryGetValue (path, out host))
+ return false;
+
+ _hosts.Remove (path);
+ }
+
+ if (host.State == ServerState.Start)
+ host.Stop (1001, String.Empty);
+
+ return true;
+ }
+
///
/// Tries to get the WebSocket service host with
/// the specified .