跳到主要内容
版本:1.3.9

创建HttpService

一、说明

HttpService是能够提供Http相关服务的基础类型。

注意

HttpService仅仅支持简单的web服务,如果是和TouchSocket的其他组件配合,则可以使用,如果想单独作为web服务器,则最好不要使用。因为其兼容性比较薄弱。

二、产品特点

  • 支持HTTPS。
  • 多种数据接收模式
  • 多地址监听(可以一次性监听多个IP及端口)

三、产品应用场景

  • HTTP基础使用场景:可跨平台、跨语言使用。

四、服务器架构

服务器在收到新客户端连接时,会创建一个HttpSocketClient的派生类实例,与远程HttpClient对应,后续的数据通信均由此实例负责。

五、支持插件接口

声明自定义实例类,然后实现IHttpPlugin接口,即可实现下列事务的触发。或者继承自HttpPluginBase类,重写相应方法即可。

插件方法功能
OnDelete当收到Delete请求时
OnGet当收到OnGet请求时
OnPost当收到OnPost请求时
OnPut当收到OnPut请求时
OnReceivedOtherHttpRequest当收到OnReceivedOtherHttpRequest请求时

六、创建HttpService

HttpService的创建,基本和TcpService一致,也可以通过继承实现,下列仅演示最简单实现。

HttpService的相关事务,会通过插件触发。

var service = new HttpService();
service.Setup(new TouchSocketConfig()//加载配置
.UsePlugin()
.SetListenIPHosts(new IPHost[] { new IPHost(7789) })
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
a.Add<MyHttpPlug>();

//default插件应该最后添加,其作用是
//1、为找不到的路由返回404
//2、处理header为Option的探视跨域请求。
a.UseDefaultHttpServicePlugin();

}))
.Start();
提示

DefaultHttpServicePlugin插件最好添加在插件中,如果没有添加的话,最好自己做好缺省路由和跨域配置。

在插件中,通过重写(或实现)的方式,进入OnGetOnPostOnDeleteOnPut等函数,即可处理对应请求。

/// <summary>
/// 支持GET、Post、Put,Delete,或者其他
/// </summary>
internal class MyHttpPlug : HttpPluginBase<HttpSocketClient>
{
protected override void OnGet(HttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.UrlEquals("/success"))
{
//直接响应文字
e.Context.Response.FromText("Success").Answer();//直接回应
Console.WriteLine("处理完毕");
e.Handled = true;
}
else if (e.Context.Request.UrlEquals("/file"))
{
//直接回应文件。
e.Context.Response
.SetStatus()//必须要有状态
.FromFile(@"D:\System\Windows.iso", e.Context.Request);
}
else if (e.Context.Request.UrlEquals("/html"))
{
//回应html
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("<!DOCTYPE html>");
stringBuilder.AppendLine("<html>");
stringBuilder.AppendLine("<head>");
stringBuilder.AppendLine("<meta charset=\"utf-8\"/>");
stringBuilder.AppendLine("<title>TouchSocket</title>");
stringBuilder.AppendLine("</head>");
stringBuilder.AppendLine("<body>");
stringBuilder.AppendLine("<div id=\"kuang\" style=\"width: 50%;height: 85%;left: 25%;top:15%;position: absolute;\">");
stringBuilder.AppendLine("<a id=\"MM\" style=\"font-size: 30px;font-family: 微软雅黑;width: 100%;\">王二麻子</a>");
stringBuilder.AppendLine("<input type=\"text\" id=\"NN\" value=\"\" style=\"font-size: 30px;width:100%;position: relative;top: 30px;\"/>");
stringBuilder.AppendLine("<input type=\"button\" id=\"XX\" value=\"我好\" style=\"font-size: 30px;width: 100%;position: relative;top: 60px;\" onclick=\"javascrip
stringBuilder.AppendLine("</div>");
stringBuilder.AppendLine("</body>");
stringBuilder.AppendLine("</html>");

e.Context.Response
.SetStatus()//必须要有状态
.SetContentTypeByExtension(".html")
.SetContent(stringBuilder.ToString());
e.Context.Response.Answer();
}
base.OnGet(client, e);
}

protected override void OnPost(HttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.UrlEquals("/uploadfile"))
{
try
{
if (e.Context.Request.TryGetContent(out byte[] bodys))//一次性获取请求体
{
return;
}

while (true)//当数据太大时,可持续读取
{
byte[] buffer = new byte[1024 * 64];
int r = e.Context.Request.Read(buffer, 0, buffer.Length);
if (r == 0)
{
return;
}

//这里可以一直处理读到的数据。
}

//下面逻辑是接收小文件。

if (e.Context.Request.ContentLen > 1024 * 1024 * 100)//全部数据体超过100Mb则直接拒绝接收。
{
e.Context.Response
.SetStatus("403", "数据过大")
.Answer();
return;
}
//此操作会先接收全部数据,然后再分割数据。
//所以上传文件不宜过大,不然会内存溢出。
var multifileCollection = e.Context.Request.GetMultifileCollection();

foreach (var item in multifileCollection)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append($"文件名={item.FileName}\t");
stringBuilder.Append($"数据长度={item.Length}");
client.Logger.Info(stringBuilder.ToString());
}

e.Context.Response
.SetStatus()
.FromText("Ok")
.Answer();
}
catch (Exception ex)
{
client.Logger.Exception(ex);
}
}
base.OnPost(client, e);
}
}

七、创建加密Ssl的HttpsService

Https服务器,和http服务器几乎一样,只不过增加了一个Ssl的配置。

.SetServiceSslOption(new ServiceSslOption() 
{
Certificate = new X509Certificate2("RRQMSocket.pfx", "RRQMSocket"),
SslProtocols = SslProtocols.Tls12
}))