Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加自动连接脚本 #324

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions readme.markdown
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Fleck.Tests/Fleck.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net48;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.2" />
Expand Down
2 changes: 1 addition & 1 deletion src/Fleck/Fleck.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
<PackageProjectUrl>https://github.com/statianzo/Fleck</PackageProjectUrl>
<RepositoryUrl>https://github.com/statianzo/Fleck</RepositoryUrl>
<PackageTags>websockets server html5 events</PackageTags>
<TargetFrameworks>net40;net45;netstandard2.0;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net48;netstandard2.0;</TargetFrameworks>
</PropertyGroup>
</Project>
11 changes: 11 additions & 0 deletions src/Fleck/Interfaces/IWebSocketConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

namespace Fleck
{
/// <summary>
/// 获取自动连接脚本
/// </summary>
/// <param name="host">主机名称</param>
/// <param name="path">请求路径(去除/auto/)</param>
/// <returns></returns>
public delegate string GetAutoScriptHandler(string host, string path, string encode);
public interface IWebSocketConnection
{
Action OnOpen { get; set; }
Expand All @@ -20,5 +27,9 @@ public interface IWebSocketConnection
void Close(int code);
IWebSocketConnectionInfo ConnectionInfo { get; }
bool IsAvailable { get; }
/// <summary>
/// 获取自动连接脚本
/// </summary>
event GetAutoScriptHandler GetAutoScript;
}
}
90 changes: 79 additions & 11 deletions src/Fleck/WebSocketConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,37 @@ namespace Fleck
{
public class WebSocketConnection : IWebSocketConnection
{
public WebSocketConnection(ISocket socket, Action<IWebSocketConnection> initialize, Func<byte[], WebSocketHttpRequest> parseRequest, Func<WebSocketHttpRequest, IHandler> handlerFactory, Func<IEnumerable<string>, string> negotiateSubProtocol)
private string DefaultScript(string host)=>"<!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.0 Transitional//EN\">\r\n"
+ "<html><head><title> websocket client </title>\r\n"
+ "\t<script type = \"text/javascript\"> \r\n"
+ "\t var ws = {};\r\n"
+ "\t function init(){\r\n"
+ "\t undefined \r\n"
+ "\t msg = document.getElementById('msg'); \r\n"
+ "\t log = document.getElementById('log'); \r\n"
+ $"\t ws = new WebSocket(\"ws://{host}\"); \r\n"
+ "\t ws.onopen = function(){ undefined \r\n"
+ "\t log.innerHTML += 'server connected <br/>';\r\n"
+ "\t };\r\n"
+ "\t ws.onmessage = function(evt){ \r\n"
+ "\t undefined \r\n"
+ "\t msg.innerHTML = evt.data;\r\n"
+ "\t };\r\n"
+ "\t var form = document.getElementById('sendForm');\r\n"
+ "\t var input = document.getElementById('sendText');\r\n"
+ "\t form.addEventListener('submit', function(e){\r\n"
+ "\t e.preventDefault();\r\n"
+ "\t var val = input.value;\r\n"
+ "\t ws.send(val);\r\n"
+ "\t input.value = \"\";});\r\n"
+ "\t } \r\n"
+ "\t window.onload = init;\r\n"
+ "\t</script></head> \r\n"
+ "<body><form id=\"sendForm\"><input id=\"sendText\" placeholder=\"Text to send\" /></form>\r\n"
+ "<label>Receive:<div id = \"msg\"></div></label><label>Log:<div id = \"log\" ></div></label></body>\r\n"
+ "</html>\r\n";
public WebSocketConnection(ISocket socket, Action<IWebSocketConnection> initialize, Func<byte[],
WebSocketHttpRequest> parseRequest, Func<WebSocketHttpRequest, IHandler> handlerFactory, Func<IEnumerable<string>, string> negotiateSubProtocol)
{
Socket = socket;
OnOpen = () => { };
Expand Down Expand Up @@ -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<byte> 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<byte> data, byte[] buffer)
Expand Down
9 changes: 8 additions & 1 deletion src/Fleck/WebSocketServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public class WebSocketServer : IWebSocketServer
private readonly string _scheme;
private readonly IPAddress _locationIP;
private Action<IWebSocketConnection> _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)
{
Expand Down Expand Up @@ -84,6 +89,7 @@ public void Start(Action<IWebSocketConnection> 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")
{
Expand All @@ -100,7 +106,6 @@ public void Start(Action<IWebSocketConnection> config)
}
}
ListenForClients();
_config = config;
}

private void ListenForClients()
Expand Down Expand Up @@ -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");
Expand Down
11 changes: 8 additions & 3 deletions src/Samples/ConsoleApp/ConsoleApp.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
Expand All @@ -11,7 +11,7 @@
<RootNamespace>Fleck.Samples.ConsoleApp</RootNamespace>
<AssemblyName>Fleck.Samples.ConsoleApp</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
Expand Down Expand Up @@ -45,14 +45,19 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="client.html" />
<Content Include="client.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Fleck\Fleck.csproj">
<Project>{8B12D929-AFA9-4307-BEFF-2ED0F1070FEE}</Project>
<Name>Fleck</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
17 changes: 11 additions & 6 deletions src/Samples/ConsoleApp/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;

using System.IO;
namespace Fleck.Samples.ConsoleApp
{
class Server
Expand All @@ -11,27 +11,32 @@ static void Main()
{
FleckLog.Level = LogLevel.Debug;
var allSockets = new List<IWebSocketConnection>();
var server = new WebSocketServer("ws://0.0.0.0:8181");
var server = new WebSocketServer("ws://0.0.0.0:8000");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
var ci = socket.ConnectionInfo;
var msg = $"Connect from [{ci.ClientIpAddress}:{ci.ClientPort}]";
socket.Send(msg);
lock(allSockets)
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
lock (allSockets)
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
Console.WriteLine(message);
allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
lock (allSockets)
allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
};
});


var input = Console.ReadLine();
while (input != "exit")
{
Expand Down
3 changes: 3 additions & 0 deletions src/Samples/ConsoleApp/app.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
49 changes: 0 additions & 49 deletions src/Samples/ConsoleApp/client.html

This file was deleted.