using System;using System.Collections.Generic;using System.IO;using System.IO.Compression;using System.Linq;using System.Net;using System.Reflection;using System.Text;using System.Text.RegularExpressions;using System.Threading;using System.Threading.Tasks;public class HttpServer : IDisposable{ private const string NotFoundResponse = "<!doctype html><html><body>Resource not found</body></html>"; private readonly HttpListener httpListener; private readonly CancellationTokenSource cts = new CancellationTokenSource(); private readonly string prefixPath; private Task processingTask; public HttpServer(string listenerUriPrefix) { this.prefixPath = ParsePrefixPath(listenerUriPrefix); this.httpListener = new HttpListener(); this.httpListener.Prefixes.Add(listenerUriPrefix); } private static string ParsePrefixPath(string listenerUriPrefix) { var match = Regex.Match(listenerUriPrefix, @"http://(?:[^/]*)(?:\:\d+)?/(.*)"); if (match.Success) { return match.Groups[1].Value.ToLowerInvariant(); } else { return string.Empty; } } public void Start() { this.httpListener.Start(); this.processingTask = Task.Factory.StartNew(async () => await ProcessRequests(), TaskCreationOptions.LongRunning); } private async Task ProcessRequests() { while (!this.cts.IsCancellationRequested) { try { var context = await this.httpListener.GetContextAsync(); try { await ProcessRequest(context).ConfigureAwait(false); context.Response.Close(); } catch (Exception ex) { context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.Close(); Console.WriteLine("Error processing HTTP request\n{0}", ex); } } catch (ObjectDisposedException ex) { if ((ex.ObjectName == this.httpListener.GetType().FullName) && (this.httpListener.IsListening == false)) { return; // listener is closed/disposed } Console.WriteLine("Error processing HTTP request\n{0}", ex); } catch (Exception ex) { HttpListenerException httpException = ex as HttpListenerException; if (httpException == null || httpException.ErrorCode != 995)// IO operation aborted { Console.WriteLine("Error processing HTTP request\n{0}", ex); } } } } private Task ProcessRequest(HttpListenerContext context) { if (context.Request.HttpMethod.ToUpperInvariant() != "GET") { return WriteNotFound(context); } var urlPath = context.Request.RawUrl.Substring(this.prefixPath.Length) .ToLowerInvariant(); switch (urlPath) { case "/": if (!context.Request.Url.ToString().EndsWith("/")) { context.Response.Redirect(context.Request.Url + "/"); context.Response.Close(); return Task.FromResult(0); } else { return WriteString(context, "Hello World!", "text/plain"); } case "/favicon.ico": return WriteFavIcon(context); case "/ping": return WritePong(context); } return WriteNotFound(context); } private static Task WritePong(HttpListenerContext context) { return WriteString(context, "pong", "text/plain"); } private static async Task WriteFavIcon(HttpListenerContext context) { context.Response.ContentType = "image/png"; context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; using (var stream = File.Open("icon.png", FileMode.Open)) { var output = context.Response.OutputStream; await stream.CopyToAsync(output); } } private static Task WriteNotFound(HttpListenerContext context) { return WriteString(context, NotFoundResponse, "text/plain", 404, "NOT FOUND"); } private static async Task WriteString(HttpListenerContext context, string data, string contentType, int httpStatus = 200, string httpStatusDescription = "OK") { AddCORSHeaders(context.Response); AddNoCacheHeaders(context.Response); context.Response.ContentType = contentType; context.Response.StatusCode = httpStatus; context.Response.StatusDescription = httpStatusDescription; var acceptsGzip = AcceptsGzip(context.Request); if (!acceptsGzip) { using (var writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8, 4096, true)) { await writer.WriteAsync(data).ConfigureAwait(false); } } else { context.Response.AddHeader("Content-Encoding", "gzip"); using (GZipStream gzip = new GZipStream(context.Response.OutputStream, CompressionMode.Compress, true)) using (var writer = new StreamWriter(gzip, Encoding.UTF8, 4096, true)) { await writer.WriteAsync(data).ConfigureAwait(false); } } } private static bool AcceptsGzip(HttpListenerRequest request) { string encoding = request.Headers["Accept-Encoding"]; if (string.IsNullOrEmpty(encoding)) { return false; } return encoding.Contains("gzip"); } private static void AddNoCacheHeaders(HttpListenerResponse response) { response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate"); response.Headers.Add("Pragma", "no-cache"); response.Headers.Add("Expires", "0"); } private static void AddCORSHeaders(HttpListenerResponse response) { response.Headers.Add("Access-Control-Allow-Origin", "*"); response.Headers.Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); } private void Stop() { cts.Cancel(); if (processingTask != null && !processingTask.IsCompleted) { processingTask.Wait(); } if (this.httpListener.IsListening) { this.httpListener.Stop(); this.httpListener.Prefixes.Clear(); } } public void Dispose() { this.Stop(); this.httpListener.Close(); using (this.cts) { } using (this.httpListener) { } }}
详细解决方案
利用HttpListener创设简单的HTTP服务
热度:358 发布时间:2016-04-28 08:18:40.0
相关解决方案
- struts HTTP Status 500解决办法
- httpclient老是提示java.lang.NoSuchMethodError: org.apache.http.protocol.BasicHttpCon
- 启动tomcat后,http://localhost:8080无法打开的有关问题
- 相干tomcat HTTP Status 500的疑问,麻烦大家进来看看
- Web Service 错误:服务器未能识别 HTTP 头 SOAPAction 的值: http://tempuri.org/
- HTTP Status 404 - /jspdemo/Register.jsp,该怎么解决
- 'http://reg.163.com/login.jsp?type=1&url=http://entry.mail.163.com/coremail/fcg/,该如何处理
- org.apache.http.client.HttpClient与org.apache.commons.httpclient.HttpClient的差别
- HTTP 404有关问题
- myeclipse<%@ taglib prefix="c" uri="http://java.sun.com/jst1/core_rt"%>解决思路
- ,http 200状态码
- tomcat新手有关问题 HTTP Status 404 - /manager/
- java http 分段上载
- soap调用webservice,报错:Root element of a SOAP message must be: 'http://schemas.xmls,该怎么处理
- HTTP Status 404如何解决
- org.apache.tomcat.util.http.Parameters processParameters,该怎么解决
- 新手,HTTP Status 404 有关问题
- java http 断点上传,该如何处理
- JSP疑问<%@ taglib prefix="ht" uri="http://www.ht.com.cn/jsp/taglibs"%>该怎么处理
- weservice调用Server returned HTTP response code: 500 for URL解决方法
- HTTP Status 404 - /webproject2/servlet/login解决办法
- 报错:HTTP Status 405 - HTTP method GET is not supported by this URL解决思路
- http://newbbs.csdn.net/ 现时和老版的bbs用的还不是同一个库
- http://newbbs.csdn.net/ 现下和老版的bbs用的还不是同一个库
- Java.io.IOException: error 3 during http over WSP 这个是什么东东
- http://sourceforge.net这个网站是什么啊解决方案
- http 传送数据 每个包有大小限制码?解决办法
- Server returned HTTP response code: 403 for URL如何解决
- http://www.java-home.com重新下线,诚邀您的加入
- httpClient 错误 The server failed to respond with a valid HTTP response