前言
我们知道web项目(即B/S端程序的S端)是很容易提供API接口,供外部进行访问的,这是Web本身的特性所然。Web项目在发布后,会挂载到比如IIS管理器,上面会要求配置IP和端口号,外部访问时根据约定的IP,端口,以及约定的路由路径、请求方式、传参等就很容易外部对内API接口访问。
客户端程序(即C/S端程序的C端)对外提供API接口则不那么容易,毕竟本身客户端没有明确需要表面自身身份的IP和端口,发布好的C/S端程序拷到哪台机器都可以使用!
问题
现在有特殊场景需求,我们开发的winform (C/S架构)程序需要和上层的总控系统对接,而总控系统可能是B/S架构,它需要和我的winform程序进行接口对接,需要我暴露自身的接口,由它来调用。
这就面临一个问题:winform如何能接收外部http (GET|POST)请求?
解决过程
1.我们现在原有的项目中,新建一个HttpServerHelper类,内部封装一个Http服务器逻辑,将winform程序当作一个Http服务器,实时监听服务器的端口有没有被访问,一旦被访问则执行相关逻辑
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace DetectMonitor.Helper { public class HttpServerHelper { private readonly string selfUrl;//客户端自身(也就是该程序本身)作为服务器,需要确认以自身哪个端口来对外监听外部的访问 private readonly HttpListener myListener; private readonly Dictionary<string, Func<HttpListenerContext, Task<string>>> myRoutes; //路由映射 //构造函数 //selfListenAddrs:实际给一个 http://ip:port/就行,不用搞太多端口区分 public HttpServerHelper(string[] selfListenAddrs) { if (!HttpListener.IsSupported) { throw new NotSupportedException("当前平台不支持HttpListener"); } myListener = new HttpListener();//初始化HttpListener实例 //初始化路由映射字典 myRoutes = new Dictionary<string, Func<HttpListenerContext, Task<string>>>();// //为服务器(就是自身)添加地址和端口 (实际) foreach (string addr in selfListenAddrs) { myListener.Prefixes.Add(addr); //内容格式http://ip:port/api/ } selfUrl = selfListenAddrs[0];//记录第一个监听的地址 } //判断监听实例是否在监听 public bool IsOpen { get { return myListener.IsListening; } } //启动服务器 public void Start() { myListener.Start(); myListener.BeginGetContext(ProcessRequestCallback,myListener);//处理客户端请求 } //停止服务器 public void Stop() { myListener.Stop(); myListener.Close(); } //添加路由和处理程序的映射关系 public void AddRoute(string route, Func<HttpListenerContext,Task<string>> handler) { myRoutes.Add(route, handler); } //处理客户端(即外部程序)发来请求的处理逻辑 (这里是定义的回调函数) private async void ProcessRequestCallback(IAsyncResult result) { HttpListener listener = (HttpListener)result.AsyncState; //开始下一个请求的监听 listener.BeginGetContext(ProcessRequestCallback,listener); try { HttpListenerContext context = listener.EndGetContext(result); //获取请求方法和URL路径 string httpMethod = context.Request.HttpMethod; string url = context.Request.Url.AbsolutePath; ///context.Request....//研究下如果获取并解析获取到Post方式访问传过来的json参数信息? string responseString = "No Data!";//默认响应字符串 Func<HttpListenerContext, Task<string>> handler; //如果请求路径存在与路由映射中,执行相应的处理程序 if (myRoutes.TryGetValue(url, out handler)) { //获取处理程序返回的响应数据 responseString = await handler(context); //将响应数据编码成字节数组 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); //设置响应的内容长度和状态码 context.Response.ContentLength64 = buffer.Length; context.Response.StatusCode = (int)HttpStatusCode.OK; // 设置响应头中的 Content-Type 为 application/json 并指定字符编码为 UTF-8(修复浏览器访问GET请求时,反馈值中文乱码问题) context.Response.ContentType = "application/json; charset=utf-8"; //将响应写入输出流并关闭输出流 context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.OutputStream.Close(); } else { //如果请求不存在与路由映射中,返回404错误 context.Response.StatusCode = (int)HttpStatusCode.NotFound; context.Response.Close(); } }catch (Exception ex) { Log4NetHelper.Error("HttpServerHelper.ProcessRequestCallback:" + ex.Message); } } } }
标签:http,string,GET,myListener,System,HttpListener,context,客户端程序,using From: https://www.cnblogs.com/Jesuslovesme/p/18649540