现在我想实现客户端项目内需要集成WEB服务器,用来提供文件的展示功能,有两种方法
Nginx
目前我的项目已经从集成Nginx更换为了C#实现,因为需求还是比较简单的,不需要Nginx那么多功能。
下载Nginx放在项目根目录:如nginx/
属性
=>生成事件
=>生成前事件命令行
中添加
taskkill /f /t /im nginx.exe
xcopy /Y /i /e $(ProjectDir)\nginx $(TargetDir)\nginx
项目中启动
/// <summary>
/// 启动Nginx.
/// </summary>
private static void StartNginx()
{
try
{
StopNginx();
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string nginxPath = System.IO.Path.Combine(basePath, "nginx");
string nginxTempPath = System.IO.Path.Combine(nginxPath, "temp");
DirectoryInfo di = new DirectoryInfo(nginxTempPath);
if (!di.Exists)
{
di.Create();
}
Process mps = new Process();
ProcessStartInfo mpsi = new ProcessStartInfo("nginx.exe")
{
WorkingDirectory = nginxPath,
UseShellExecute = true,
RedirectStandardInput = false,
RedirectStandardOutput = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
mps.StartInfo = mpsi;
mps.Start();
}
catch (Exception ex)
{
LogHelper.WriteErrLog("【启动Nginx】(StartNginx)无法启动Nginx," + ex.Message, ex);
}
}
/// <summary>
/// 关闭Nginx.
/// </summary>
private static void StopNginx()
{
try
{
Process[] processes = Process.GetProcessesByName("nginx");
foreach (Process p in processes)
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string nginxPath = System.IO.Path.Combine(basePath, "nginx", "nginx.exe");
try
{
if (nginxPath == p.MainModule.FileName)
{
p.Kill();
p.Close();
}
}
catch (Exception ex)
{
LogHelper.WriteErrLog("【停止Nginx】(StartNginx)无法停止Nginx," + ex.Message, ex);
}
}
}
catch (Exception ex)
{
LogHelper.WriteErrLog("【停止Nginx】(StartNginx)无法和获取到系统进程," + ex.Message, ex);
}
}
端口号和服务目录都在Nginx的配置文件中配置
using System;
using System.Net;
namespace SchoolClient.Utils.HttpServer
{
public class ZServerHelper
{
private HttpListener httpListener = new HttpListener();
private string basePath = "";
public void Setup(string basePath, int port = 8080)
{
this.basePath = basePath;
httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
httpListener.Prefixes.Add(string.Format("http://*:{0}/", port));
httpListener.Start();//开启服务
Receive();//异步接收请求
}
private void Receive()
{
httpListener.BeginGetContext(new AsyncCallback(EndReceive), null);
}
private void EndReceive(IAsyncResult ar)
{
HttpListenerContext context = httpListener.EndGetContext(ar);
ZDispather(context);//解析请求
Receive();
}
private ZRequestHelper RequestHelper;
private ZResponseHelper ResponseHelper;
private void ZDispather(HttpListenerContext context)
{
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
RequestHelper = new ZRequestHelper(request, basePath);
ResponseHelper = new ZResponseHelper(response);
RequestHelper.DispatchResources(fs =>
{
ResponseHelper.WriteToClient(fs);// 对相应的请求做出回应
});
}
}
}
using System;
using System.IO;
using System.Net;
namespace SchoolClient.Utils.HttpServer
{
public class ZRequestHelper
{
private HttpListenerRequest request;
private string basepath = "";
public ZRequestHelper(HttpListenerRequest request, string basepath)
{
this.request = request;
this.basepath = basepath;
}
public delegate void ExecutingDispatch(FileStream fs);
public void DispatchResources(ExecutingDispatch action)
{
string rawUrl = request.RawUrl;
string rawPath = rawUrl.Replace("/", Path.DirectorySeparatorChar + "");
//这里对应请求其他类型资源,如图片,文本等
string filePath = string.Format(@"{0}{1}", basepath, rawPath);
//默认文档为index.html
if (rawUrl.Length == 1)
{
filePath = string.Format(@"{0}/index.html", basepath);
}
filePath = filePath.Replace(Path.DirectorySeparatorChar + "" + Path.DirectorySeparatorChar, Path.DirectorySeparatorChar + "");
try
{
if (File.Exists(filePath))
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
action?.Invoke(fs);
}
}
catch { return; }
}
}
}
using System;
using System.IO;
using System.Net;
namespace SchoolClient.Utils.HttpServer
{
public class ZResponseHelper
{
private HttpListenerResponse response;
public ZResponseHelper(HttpListenerResponse response)
{
this.response = response;
outputStream = response.OutputStream;
}
public Stream outputStream { get; set; }
public class FileObject
{
public FileStream fs;
public byte[] buffer;
}
public void WriteToClient(FileStream fs)
{
response.StatusCode = 200;
byte[] buffer = new byte[1024];
FileObject obj = new FileObject() { fs = fs, buffer = buffer };
fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(EndWrite), obj);
}
private void EndWrite(IAsyncResult ar)
{
FileObject obj = ar.AsyncState as FileObject;
int num = obj.fs.EndRead(ar);
outputStream.Write(obj.buffer, 0, num);
if (num < 1)
{
obj.fs.Close(); //关闭文件流
outputStream.Close();//关闭输出流,如果不关闭,浏览器将一直在等待状态
obj.fs.Dispose();
outputStream.Dispose();
return;
}
obj.fs.BeginRead(obj.buffer, 0, obj.buffer.Length, new AsyncCallback(EndWrite), obj);
}
}
}
项目根目录创建文件夹wwwroot
属性
=>生成事件
=>生成前事件命令行
中添加
xcopy /Y /i /e $(ProjectDir)\wwwroot $(TargetDir)\wwwroot
项目中启动
public static string basePath = AppDomain.CurrentDomain.BaseDirectory;
public static string wwwrootPath = $"{basePath}wwwroot\\";
public void startHttpServer()
{
new Thread(
o =>
{
new ZServerHelper().Setup(wwwrootPath, 8899);
}
)
{ IsBackground = true }
.Start();
}