发布时间:2020-07-09责任编辑:满帅 浏览:1948
为什么不用asp.netcore 呢?
如果我只需要一点向外提供Web服务的功能呢。
比如,托管程序的更新包,或者只是显示一张图片…
主角:WebListener
WebListener 通过Nuget 包安装,它比HttpListener 要新。具体区别,忘了,可以Google查一下。
当然,.NetFramework 也行。
var _webListener = new WebListener();
_webListener.Settings.UrlPrefixes.Add($"http://*:8088");
_webListener.Start();
Thread thread = new Thread(HttpHandler);
thread.Start();
private async void HttpHandler()
{
while (_listening)
{
RequestContext context = null;
try
{
context = await _webListener.AcceptAsync();
} catch (Exception ex)
{
ex = ex.Demystify();
_logger.LogError($"an error occur due AcceptAsync request :> {ex.Message}");
continue;
}
ThreadPool.QueueUserWorkItem((_) =>
{
var segments = context.Request.RawUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length > 0)
{
string methodName = segments[0];
string[] strParams = segments.Skip(1).ToArray();
var method = GetType().GetMethods()
.Where(mi => mi.GetCustomAttributes(true)
.Any(attr => attr is Mapping map && map.Map.Equals(methodName,StringComparison.OrdinalIgnoreCase)))
.FirstOrDefault();
if (method != null)
{
try
{
List<object> @params = method
.GetParameters()
.Skip(1)
.Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType)).ToList();
@params.Insert(0, context);
method.Invoke(this, @params.ToArray());
} catch (Exception ex)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ReasonPhrase = ex.Message;
}
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
context.Dispose();
});
}
}
监听到的请求会找到带有Mapping特性的方法来处理,Map字段代表请求中第一个路径的名称比如http://server/image
[AttributeUsage(AttributeTargets.Method)]
class Mapping :Attribute
{
public string Map;
public Mapping(string s)
{
Map = s;
}
}
[Mapping("image")]
public async void HttpImageHandler(RequestContext context, string path)
{
string decodePath = HttpUtility.UrlDecode(path);
string filePath = Path.Combine(_appConfigOptions.Value?.AvatarStorePath,
decodePath);
if (File.Exists(filePath))
{
await context.Response.SendFileAsync(filePath, 0, null, context.DisconnectToken);
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
}
不算复杂,简单的Web服务和超简单的路由就实现了。
外包部供稿