diff --git a/Apewer.Web/WebSocket/ChatServer.cs b/Apewer.Web/WebSocket/ChatServer.cs
index db99b1d..4ba3425 100644
--- a/Apewer.Web/WebSocket/ChatServer.cs
+++ b/Apewer.Web/WebSocket/ChatServer.cs
@@ -4,6 +4,7 @@ using Apewer;
 using Apewer.Network;
 using System;
 using System.Collections.Generic;
+using System.Net;
 
 namespace Apewer.WebSocket
 {
@@ -127,18 +128,19 @@ namespace Apewer.WebSocket
             _websocket = new GenericServer();
             lock (_websocket)
             {
-                var ws = _websocket.Start(_websocketport, _websocketaddress);
-                if (ws)
+                try
                 {
+                    _websocket.Start(_websocketport, IPAddress.Parse(_websocketaddress));
+
                     _websocket.OnMessage += WebSocketReceived;
                     _websocket.OnOpen += WebsocketOnOpen;
                     _websocket.OnClose += WebsocketOnClose;
                     RaiseConsole("WebSocket 服务已启动。");
                 }
-                else
+                catch (Exception ex)
                 {
                     _websocket = null;
-                    RaiseError("WebSocket 服务启动失败。");
+                    RaiseError($"WebSocket 服务启动失败:{ex.Message()}");
                     return;
                 }
 
@@ -426,7 +428,7 @@ namespace Apewer.WebSocket
             {
                 var input = Console.ReadLine();
                 if (input == "exit") break;
-                ws.Send(ws.Address, ":", ws.Port.ToString(), "\n", input);
+                ws.Send(ws.Address.ToString(), ":", ws.Port.ToString(), "\n", input);
             }
 
             ws.Close();
diff --git a/Apewer.Web/WebSocket/GenericServer.cs b/Apewer.Web/WebSocket/GenericServer.cs
index 608fba7..cba756c 100644
--- a/Apewer.Web/WebSocket/GenericServer.cs
+++ b/Apewer.Web/WebSocket/GenericServer.cs
@@ -3,6 +3,7 @@
 using Apewer;
 using System;
 using System.Collections.Generic;
+using System.Net;
 
 namespace Apewer.WebSocket
 {
@@ -11,15 +12,12 @@ namespace Apewer.WebSocket
     public sealed class GenericServer : IDisposable
     {
 
-        const string DefaultAddress = "0.0.0.0";
-        const ushort DefaultPort = 8000;
-
         private Dictionary<int, Connection> _connections = new Dictionary<int, Connection>();
         private WebSocketServer _server = null;
 
         private bool _running = false;
-        private string _address = null;
-        private int _port = DefaultPort;
+        private IPAddress _address = null;
+        private int _port = 0;
 
         /// <summary></summary>
         public event SocketEvent OnOpen;
@@ -54,7 +52,7 @@ namespace Apewer.WebSocket
         }
 
         /// <summary>监听的地址。</summary>
-        public string Address
+        public IPAddress Address
         {
             get { return _address; }
         }
@@ -101,28 +99,46 @@ namespace Apewer.WebSocket
             _running = false;
         }
 
+        /// <summary>启动监听,如果监听正在运行则失败。在所有 IPv4 网络接口上自动选择可用的端口号。</summary>
+        /// <returns>已监听的端口号。</returns>
+        /// <exception cref="FormatException" />
+        /// <exception cref="InvalidOperationException" />
+        public void Start() => Start(0, null);
+
         /// <summary>启动监听,如果监听正在运行则失败。</summary>
-        public bool Start(int port = DefaultPort, string address = DefaultAddress)
+        /// <param name="endPoint">要监听的终结点。指定为 NULL 时将在所有 IPv4 网络接口上自动选择可用的端口号。</param>
+        /// <returns>已监听的端口号。</returns>
+        /// <exception cref="ArgumentOutOfRangeException" />
+        /// <exception cref="FormatException" />
+        /// <exception cref="InvalidOperationException" />
+        public void Start(IPEndPoint endPoint)
         {
-            if (address == null) return false;
-            if (_running) return false;
-
-            _address = address ?? "";
-            _port = NumberUtility.Restrict( port, 0, ushort.MaxValue);
+            if (endPoint == null) Start(0, null);
+            else Start(endPoint.Port, endPoint.Address);
+        }
 
-            try
-            {
-                var location = "ws://" + address + ":" + port.ToString();
-                _server = new WebSocketServer(location);
-                _server.Start(Initialize);
-                _running = true;
-                return true;
-            }
-            catch (Exception exception)
-            {
-                RaiseExcepted(exception);
-                return false;
-            }
+        /// <summary>启动监听,如果监听正在运行则失败。</summary>
+        /// <param name="port">要监听的端口号。指定为 0 时将自动选择可用的端口号。</param>
+        /// <param name="address">要监听的网络接口。指定为 NULL 时将在所有 IPv4 网络接口监听,等同于 <see cref="IPAddress.Any"/>。</param>
+        /// <returns>已监听的端口号。</returns>
+        /// <exception cref="ArgumentOutOfRangeException" />
+        /// <exception cref="FormatException" />
+        /// <exception cref="InvalidOperationException" />
+        public void Start(int port, IPAddress address = null)
+        {
+            if (address == null) address = IPAddress.Any;
+            if (port < 0) throw new ArgumentOutOfRangeException(nameof(port));
+            if (port > 65535) throw new ArgumentOutOfRangeException(nameof(port));
+            if (_running) throw new InvalidOperationException("示例已经在运行中,无法再次启动。");
+
+            _address = address;
+            _port = port;
+
+            var location = "ws://" + _address.ToString() + ":" + port.ToString();
+            _server = new WebSocketServer(location);
+            _server.Start(Initialize);
+            _port = _server.Port;
+            _running = true;
         }
 
         /// <summary>对所有连接发送文本。</summary>