前言
现在我想实现客户端项目内需要集成WEB服务器,用来提供文件的展示功能,有两种方法
目前我的项目已经从集成Nginx更换为了C#实现,因为需求还是比较简单的,不需要Nginx那么多功能。
集成Nginx
下载Nginx放在项目根目录:如nginx/
属性=>生成事件=>生成前事件命令行中添加
1 2
| taskkill /f /t /im nginx.exe xcopy /Y /i /e $(ProjectDir)\nginx $(TargetDir)\nginx
|
项目中启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
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); } }
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的配置文件中配置
C#实现
工具类(ZServerHelper)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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); }); } } }
|
请求(ZRequestHelper)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| 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); 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; } } } }
|
响应(ZResponseHelper)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| 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; try { 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); } catch (Exception) { obj.fs?.Close(); outputStream?.Close(); obj.fs?.Dispose(); outputStream?.Dispose(); } } } }
|
调用
项目根目录创建文件夹wwwroot
属性=>生成事件=>生成前事件命令行中添加
1
| xcopy /Y /i /e $(ProjectDir)\wwwroot $(TargetDir)\wwwroot
|
项目中启动
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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(); }
|