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>