diff --git a/readme.markdown b/readme.markdown index 14f1fd07..2fe74176 100644 --- a/readme.markdown +++ b/readme.markdown @@ -1,6 +1,36 @@ Fleck === +分支功能: +--- +增加自动连接脚本功能,实现采用http访问时可自动连接本服务器,无须自己构建客户端脚本 + +分支示例 +--- +服务端代码详见示例,编译并运行后,在浏览器中输入【http://localhost:8000/auto 】即可访问本服务器 +后缀/auto不可少 +```cs +private string GetAutoScript(string host, string path,string encode) +{ + const string LocalHost = "127.0.0.1:8000";//脚本中的服务器地址 + //加载自动连接脚本模板,根据路径选择不同模板 + var fileClient = (string.IsNullOrEmpty(path) + || !path.EndsWith("/debug",StringComparison.OrdinalIgnoreCase)) + ? Path.Combine(nvr.ModelsDir, "client.html") + : Path.Combine(nvr.ModelsDir, "debug.html"); + if (!File.Exists(fileClient)) + return string.Empty; + var script = File.ReadAllText(fileClient, Encoding.ASCII); + if(!string.IsNullOrEmpty(script)) + script= script.Replace(LocalHost, host);//用host替换脚本中的服务器地址 + return script; +} + +var server = new WebSocketServer("ws://0.0.0.0:8000"); + server.GetAutoScript += GetAutoScript; +... +``` + [![Build status](https://ci.appveyor.com/api/projects/status/k0s8hq5y4emak5j3/branch/master?svg=true)](https://ci.appveyor.com/project/statianzo/fleck/branch/master) [![NuGet](https://img.shields.io/nuget/v/Fleck.svg)](https://www.nuget.org/packages/Fleck/) Fleck is a WebSocket server implementation in C#. Branched from the diff --git a/src/Fleck.Tests/Fleck.Tests.csproj b/src/Fleck.Tests/Fleck.Tests.csproj index 0fc44433..399e721c 100644 --- a/src/Fleck.Tests/Fleck.Tests.csproj +++ b/src/Fleck.Tests/Fleck.Tests.csproj @@ -1,6 +1,6 @@  - net45;netcoreapp2.0 + net48;netcoreapp2.0 diff --git a/src/Fleck/Fleck.csproj b/src/Fleck/Fleck.csproj index 3a6fabc3..1e669f31 100644 --- a/src/Fleck/Fleck.csproj +++ b/src/Fleck/Fleck.csproj @@ -9,6 +9,6 @@ https://github.com/statianzo/Fleck https://github.com/statianzo/Fleck websockets server html5 events - net40;net45;netstandard2.0;netcoreapp2.0 + net48;netstandard2.0; diff --git a/src/Fleck/Interfaces/IWebSocketConnection.cs b/src/Fleck/Interfaces/IWebSocketConnection.cs index 09a2cdae..b1201e73 100644 --- a/src/Fleck/Interfaces/IWebSocketConnection.cs +++ b/src/Fleck/Interfaces/IWebSocketConnection.cs @@ -3,6 +3,13 @@ namespace Fleck { + /// + /// 获取自动连接脚本 + /// + /// 主机名称 + /// 请求路径(去除/auto/) + /// + public delegate string GetAutoScriptHandler(string host, string path, string encode); public interface IWebSocketConnection { Action OnOpen { get; set; } @@ -20,5 +27,9 @@ public interface IWebSocketConnection void Close(int code); IWebSocketConnectionInfo ConnectionInfo { get; } bool IsAvailable { get; } + /// + /// 获取自动连接脚本 + /// + event GetAutoScriptHandler GetAutoScript; } } diff --git a/src/Fleck/WebSocketConnection.cs b/src/Fleck/WebSocketConnection.cs index 5aba2740..aaf2efae 100644 --- a/src/Fleck/WebSocketConnection.cs +++ b/src/Fleck/WebSocketConnection.cs @@ -8,7 +8,37 @@ namespace Fleck { public class WebSocketConnection : IWebSocketConnection { - public WebSocketConnection(ISocket socket, Action initialize, Func parseRequest, Func handlerFactory, Func, string> negotiateSubProtocol) + private string DefaultScript(string host)=>"\r\n" + + " websocket client \r\n" + + "\t \r\n" + + "
\r\n" + + "\r\n" + + "\r\n"; + public WebSocketConnection(ISocket socket, Action initialize, Func parseRequest, Func handlerFactory, Func, string> negotiateSubProtocol) { Socket = socket; OnOpen = () => { }; @@ -127,21 +157,59 @@ public void Close(int code) SendBytes(bytes, CloseSocket); } + private string DoGetAutScript(string host,string path,string encode) + { + var result = GetAutoScript?.Invoke(host, path, encode); + if(string.IsNullOrEmpty(result)) + result= DefaultScript(host); + return result; + } + public event GetAutoScriptHandler GetAutoScript; + + private void SendScript(WebSocketHttpRequest request,string path) + { + var CultureInfo = "zh-CN"; + if(request.Headers.ContainsKey("Accept-Language")) + { + CultureInfo = request.Headers["Accept-Language"].Split(',')[0]; + } + request.Headers["Accept-Language"].Split(','); + var msg = System.Text.Encoding.UTF8.GetBytes(DoGetAutScript(request.Headers["Host"], path, CultureInfo)); + var head = System.Text.Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\n" + + "Connection: Keep-Alive\r\n" + + $"Content-Length: {msg.Length}\r\n" + + "Content-Type: text/html\r\n" + + $"Date: {DateTime.UtcNow.ToString("r", System.Globalization.CultureInfo.GetCultureInfo(CultureInfo))}\r\n" + + "\r\n"); + var frame = head.Concat(msg).ToArray(); + var task=SendBytes(frame, null); + task.Wait(3000); + Close(); + } public void CreateHandler(IEnumerable data) { var request = _parseRequest(data.ToArray()); if (request == null) return; - Handler = _handlerFactory(request); - if (Handler == null) - return; - var subProtocol = _negotiateSubProtocol(request.SubProtocols); - ConnectionInfo = WebSocketConnectionInfo.Create(request, Socket.RemoteIpAddress, Socket.RemotePort, subProtocol); - - _initialize(this); - - var handshake = Handler.CreateHandshake(subProtocol); - SendBytes(handshake, OnOpen); + if(string.Equals(request.Headers["Connection"], + "keep-alive", StringComparison.OrdinalIgnoreCase)) + { + if(request.Path.StartsWith("/Auto", StringComparison.OrdinalIgnoreCase)) + SendScript(request,request.Path.Substring(5)); + else + Close(WebSocketStatusCodes.ProtocolError); + return; + } + Handler = _handlerFactory(request); + if (Handler == null) + return; + var subProtocol = _negotiateSubProtocol(request.SubProtocols); + ConnectionInfo = WebSocketConnectionInfo.Create(request, Socket.RemoteIpAddress, Socket.RemotePort, subProtocol); + + _initialize(this); + + var handshake = Handler.CreateHandshake(subProtocol); + SendBytes(handshake, OnOpen); } private void Read(List data, byte[] buffer) diff --git a/src/Fleck/WebSocketServer.cs b/src/Fleck/WebSocketServer.cs index f8f3e404..86f117f9 100644 --- a/src/Fleck/WebSocketServer.cs +++ b/src/Fleck/WebSocketServer.cs @@ -14,6 +14,11 @@ public class WebSocketServer : IWebSocketServer private readonly string _scheme; private readonly IPAddress _locationIP; private Action _config; + private string DoGetAutScript(string host, string path,string encode) + { + return GetAutoScript?.Invoke(host,path, encode); + } + public event GetAutoScriptHandler GetAutoScript; public WebSocketServer(string location, bool supportDualStack = true) { @@ -84,6 +89,7 @@ public void Start(Action config) ListenerSocket.Bind(ipLocal); ListenerSocket.Listen(100); Port = ((IPEndPoint)ListenerSocket.LocalEndPoint).Port; + _config = config; FleckLog.Info(string.Format("Server started at {0} (actual port {1})", Location, Port)); if (_scheme == "wss") { @@ -100,7 +106,6 @@ public void Start(Action config) } } ListenForClients(); - _config = config; } private void ListenForClients() @@ -146,6 +151,8 @@ private void OnClientConnect(ISocket clientSocket) b => connection.OnPong(b)), s => SubProtocolNegotiator.Negotiate(SupportedSubProtocols, s)); + connection.GetAutoScript += DoGetAutScript; + if (IsSecure) { FleckLog.Debug("Authenticating Secure Connection"); diff --git a/src/Samples/ConsoleApp/ConsoleApp.csproj b/src/Samples/ConsoleApp/ConsoleApp.csproj index 57c0df0f..42397135 100644 --- a/src/Samples/ConsoleApp/ConsoleApp.csproj +++ b/src/Samples/ConsoleApp/ConsoleApp.csproj @@ -1,5 +1,5 @@  - + Debug x86 @@ -11,7 +11,7 @@ Fleck.Samples.ConsoleApp Fleck.Samples.ConsoleApp 512 - v4.5 + v4.8 @@ -45,7 +45,9 @@ - + + PreserveNewest + @@ -53,6 +55,9 @@ Fleck + + +