HttpListener实现简单的Http服务监听

单独两个程序通过http服务监听完成数据通讯,主要实现思路如下:

1、程序一启动监听固定IP地址(也可以是任意IP)及固定端口的监听,收到http请求后对请求内容进行解析,并根据MessageType(逻辑代码)进行不同逻辑处理,根据处理结果告知http请求发送程序结果。

2、程序二启动监听固定IP地址(也可以是任意IP)及固定端口的监听,收到http请求后对请求内容进行解析,并根据MessageType(逻辑代码)进行不同逻辑处理,根据处理结果告知http请求发送程序结果。

注意:

1、如果两个程序需要互相通讯至少要求两个程序之前的端口不同

2、为达到量程序互相通讯目的,两个程序既要对固定IP(也可以是任意IP)端口进行监听,还要能够发送http请求。

3、为确保两个程序能够收到消息,程序一监听的端口必须是程序二请求的端口,程序二监听的端口必须是程序一请求的端口。

程序一代码如下:

被动接收数据时需要启动IP端口监听


        /// <summary>
        /// 通讯IP地址
        /// </summary>
        public string ListenerIp = "127.0.0.1";

        /// <summary>
        /// 指令下发监听端口
        /// </summary>
        private static string IssuePort = ConfigurationManager.AppSettings["IssuePort"];
        /// <summary>
        /// 数据上传监听端口
        /// </summary>
        private static string UploadPort = ConfigurationManager.AppSettings["UploadPort"];

        /// <summary>
        /// http监听对象
        /// </summary>
        public HttpListener listener;
        public void Init()
        {

            try
            {
                //启动数据接收监听IP及端口
                string listenerUrl = $"http://{ListenerIp}:{UploadPort}/";
                listener = new HttpListener();
                listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                listener.Prefixes.Add(listenerUrl);
                listener.Start();
                //开始监听
                listener.BeginGetContext(ListenerHandle, listener); //开始监听

            }
            catch (Exception e)
            {
                OnWriteLogDebug($"启用数据监听失败!{e.Message}");
            }
        }

        /// <summary>
        /// http监听获取到数据后的回调事件
        /// </summary>
        /// <param name="result"></param>
        private void ListenerHandle(IAsyncResult result)
        {
            JObject jobject = new JObject();
            //继续异步监听
            listener.BeginGetContext(ListenerHandle, null);

            //获得context对象
            var context = listener.EndGetContext(result);
            HttpListenerRequest request = context.Request;
            var response = context.Response;
            如果是js的ajax请求,还可以设置跨域的ip地址与参数
            context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域参数设置,通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域请求设置,通常设置为配置文件
            context.Response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
            context.Response.AddHeader("Content-type", "application/x-www-form-urlencoded");//添加响应头信息
            context.Response.ContentEncoding = Encoding.UTF8;
            try
            {
                //当接收到请求后程序流会走到这里
                Console.ForegroundColor = ConsoleColor.White;

                Stream streams = request.InputStream;
                StreamReader reader = new StreamReader(streams, Encoding.UTF8);
                string requestData = reader.ReadToEnd();

                OnWriteLogDebug("收到请求原始数据:" + requestData.ToString());
         
                //数据解析逻辑
                sdkCallback(requestData);

                //接收到http消息后的数据返回
                jobject.Add("code", 0);
                jobject.Add("data", "");
                jobject.Add("result", true);
               
            }
            catch (Exception ex)
            {
                OnWriteLogDebug($"数据解析异常:{ex.Message},时间:{ DateTime.Now.ToString()}\r\n");
                jobject.Add("code", 1);
                jobject.Add("data", "");
                jobject.Add("result", false);
            }
            finally
            {
                String hingeString = Newtonsoft.Json.JsonConvert.SerializeObject(jobject);
                var returnByteArr = Encoding.UTF8.GetBytes(hingeString);//设置客户端返回信息的编码*/
                response.StatusCode = 200;
                response.ContentType = "application/json";
                response.ContentEncoding = Encoding.UTF8;
                using (var stream = response.OutputStream)
                {
                    //把处理信息返回到客户端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
        }

        /// <summary>
        /// 采集到的数据解析
        /// </summary>
        /// <param name="szData"></param>
        /// <param name="nDataLength"></param>
        /// <returns></returns>
        private bool sdkCallback(string szData)
        {
            try
            {
                Newtonsoft.Json.Linq.JObject data = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(szData);

                string MessageType = data["MessageType"].ToString();
                if (MessageType == "逻辑类型")
                {
                    ItemInfo info = new ItemInfo();
                    info.DoorId = int.Parse(data["DoorId"].ToString());
                    info.DeviceType = int.Parse(data["DeviceType"].ToString());
                    info.EventType = (EmEventType)Enum.Parse(typeof(EmEventType), data["EventType"].ToString());

                    var Values = data["Values"].ToString();
                    //数据更新或入库
                    UpdateTag(info, Values);
                }
            }
            catch (Exception ex)
            {
                OnWriteLogDebug("数据解析异常:" + ex);
                return false;
            }

            return true;
        }

程序一主动发送数据

private bool SendCommand(JObject jObject)
        {
            using (WebClient webClient = new WebClient())
            {
                try
                {                    
                    webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
                    string url = $"http://{ListenerIp}:{IssuePort}/";
                    byte[] bytesRtn = webClient.UploadData(url, Encoding.ASCII.GetBytes(jObject.ToString()));
                    string json = Encoding.UTF8.GetString(bytesRtn);
                    Newtonsoft.Json.Linq.JObject jobject = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
                    OnWriteLogDebug("下发数据结果:" + jobject.ToString());
                    return (string)jobject["code"] == "0";
                }
                catch (Exception ex)
                {
                    OnWriteLogError("SendCommand: "+ex.ToString());
                    return false;
                }
            }
        }

程序二代码如下(代码与程序一基本一致):

被动接收数据时需要启动IP端口监听

        /// <summary>
        /// 接口与采集控制台通讯IP地址
        /// </summary>
        private static string ListenerIp = "127.0.0.1";
        /// <summary>
        /// 指令下发监听端口
        /// </summary>
        private static string IssuePort = ConfigurationManager.AppSettings["IssuePort"];
        /// <summary>
        /// 数据上传监听端口
        /// </summary>
        private static string UploadPort = ConfigurationManager.AppSettings["UploadPort"];
        static void Main(string[] args)
        {
            try
            {

                listener = new HttpListener();
                listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;

                string listenerUrl = $"http://{ListenerIp}:{IssuePort}/";
                listener.Prefixes.Add(listenerUrl);

                listener.Start();
                listener.BeginGetContext(ListenerHandle, listener); //开始监听
            }
            catch (Exception ex)
            {
                Console.WriteLine("指令下发端口监听任务启动失败:" + ex.Message);
            }
            finally
            {
                Console.ReadLine();
            }
        }

        private static void ListenerHandle(IAsyncResult result)
        {
            JObject jobject = new JObject();
            //继续异步监听
            listener.BeginGetContext(ListenerHandle, null);

            //获得context对象
            var context = listener.EndGetContext(result);

            HttpListenerRequest request = context.Request;
            var response = context.Response;
            如果是js的ajax请求,还可以设置跨域的ip地址与参数
            context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域参数设置,通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域请求设置,通常设置为配置文件
            context.Response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
            context.Response.AddHeader("Content-type", "application/x-www-form-urlencoded");//添加响应头信息
            context.Response.ContentEncoding = Encoding.UTF8;

            try
            {
                //当接收到请求后程序流会走到这里
                Console.ForegroundColor = ConsoleColor.White;

                Stream streams = request.InputStream;
                StreamReader reader = new StreamReader(streams, Encoding.UTF8);
                string requestData = reader.ReadToEnd();

                Console.WriteLine($"指令下发接收接001{requestData},时间:{ DateTime.Now.ToString()}\r\n");
                Newtonsoft.Json.Linq.JObject json = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(requestData);
                Console.WriteLine($"指令下发接收接002{json.ToString()},时间:{ DateTime.Now.ToString()}\r\n");

                bool result1 = false;//返回数据类型
                #region 接收命令解析处理开始
                if (json["dataType"].ToString() == "逻辑类型")
                {
                    string UserName = (string)json["UserName"];
                    string Password = (string)json["Password"];
                    //逻辑代码
                    result1 = Connect(UserName, Password);
                }
                else
                {
                    Console.WriteLine($"指令下发失败,未识别的指令信息,时间:{ DateTime.Now.ToString()}\r\n");
                }
                #endregion 接收命令解析处理结束

                if (result1)
                {
                    jobject.Add("code", 0);
                    jobject.Add("data", "");
                    jobject.Add("result", true);

                }
                else
                {
                    jobject.Add("code", 1);
                    jobject.Add("data", "");
                    jobject.Add("result", false);
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;

                jobject.Add("code", 1);
                jobject.Add("data", "");
                jobject.Add("result", false);
            }
            finally
            {
                String hingeString = Newtonsoft.Json.JsonConvert.SerializeObject(jobject);
                var returnByteArr = Encoding.UTF8.GetBytes(hingeString);//设置客户端返回信息的编码*/
                response.StatusCode = 200;
                response.ContentType = "application/json";
                response.ContentEncoding = Encoding.UTF8;
                using (var stream = response.OutputStream)
                {
                    //把处理信息返回到客户端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
        }

程序二数据发送逻辑


        private static void PrintMessage()
        {
            
                try
                {
                    
                        JObject jObject = new JObject();
                        jObject.Add("DoorId", int.Parse(ADV_Hid.InnerText));
                        jObject.Add("DeviceType", int.Parse(ADV_DeviceType.InnerText));
                        jObject.Add("EventType", EmEventType.ADVStatus.ToString());
                        jObject.Add("Values", ADV_Status.InnerText);
                        jObject.Add("MessageType", "messageQueue");

                        string result = WebServiceApp(jObject.ToString());
                        Console.WriteLine("请求结果:" + result);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("消息解析异常:" + sMessage + " " + ex.Message);
                }
            }
        }

        /// <summary>
        /// 将回调事件的结果提交给接口
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string WebServiceApp(string param)
        {
            try
            {
                //转换输入参数的编码类型,获取bytep[]数组 
                byte[] byteArray = Encoding.UTF8.GetBytes(param);
                //初始化新的webRequst
                //1. 创建httpWebRequest对象

                string pushUrl = $"http://{ListenerIp}:{UploadPort}/";
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(pushUrl);
                webRequest.KeepAlive = false;
                webRequest.AllowAutoRedirect = true;
                webRequest.CookieContainer = new CookieContainer();
                //2. 初始化HttpWebRequest对象
                webRequest.Method = "POST";
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.ContentLength = byteArray.Length;
                //3. 附加要POST给服务器的数据到HttpWebRequest对象(附加POST数据的过程比较特殊,它并没有提供一个属性给用户存取,需要写入HttpWebRequest对象提供的一个stream里面。)
                Stream newStream = webRequest.GetRequestStream();//创建一个Stream,赋值是写入HttpWebRequest对象提供的一个stream里面
                newStream.Write(byteArray, 0, byteArray.Length);
                newStream.Close();
                //4. 读取服务器的返回信息
                HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
                StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                string phpend = php.ReadToEnd();
                return phpend;
            }
            catch (Exception e)
            {
                return "请求异常" + e;
            }
        }

备注:由于当时实现功能时两个程序在同一台服务器,所以监听的IP地址都是127.0.0.1,如果要监听不同的IP地址,需要大家自行研究启动监听时的IP地址是对方的IP还是自己的IP。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值