IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> C#如何使用HttpListener监听POST请求并解析Body中的参数 -> 正文阅读

[网络协议]C#如何使用HttpListener监听POST请求并解析Body中的参数

1.问题描述

做一个二维码摆渡机的发送端接收端程序,用于网络物理隔离。摆渡机是第三方厂家的设备,该设备提供一个接口用于接收发送端传输的数据,摆渡机处理该数据并调用接收端的接口,将数据传递给接收端。

本文主要记录接收端程序如何使用 HttpListener 进行监听HTTP请求,并且解析POST请求中携带的参数。如何构造 content-typemultipart/form-data; boundary= 的POST请求,请参考:https://cylycgs.blog.csdn.net/article/details/101019468

下面是发送端和接收端的截图:
在这里插入图片描述

2.使用HttpListener监听

关于HttpListener的官方文档在这里:https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=netframework-4.5

如下是关于如何使用 HttpListener 的相关代码,有详细的注释:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace HttpListenerDemo
{
    public partial class FrmResponse : Form
    {
        private static HttpListener httpListener = null;

        public FrmResponse()
        {
            InitializeComponent();
        }

        /// <summary>
        /// HttpListener 监听http的回调函数
        /// </summary>
        /// <param name="ar"></param>
        private void GetHttpListenerCallBack(IAsyncResult ar)
        {
            try
            {
                httpListener = ar.AsyncState as HttpListener;
                HttpListenerContext context = httpListener.EndGetContext(ar);
                httpListener.BeginGetContext(new AsyncCallback(GetHttpListenerCallBack), httpListener);

                var request = context.Request;
                var response = context.Response;

                response.ContentType = "text/plain;charset=UTF-8"; // 告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
                response.AddHeader("Content-type", "text/plain"); // 添加响应头信息
                response.ContentEncoding = Encoding.UTF8;
                string returnObj = null; // 定义返回客户端的信息

                if (request.HttpMethod == "POST" && request.ContentLength64 > 0)
                {
                    // 处理客户端发送的请求并返回处理信息
                    returnObj = HandleRequest(request, response);
                }
                else
                {
                    returnObj = $"必须是POST请求,并且必须传参";
                    response.StatusDescription = "400";
                    response.StatusCode = 400;
                }
                var returnByteArr = Encoding.UTF8.GetBytes(returnObj); // 设置客户端返回信息的编码
                try
                {
                    using (var stream = response.OutputStream)
                    {
                        // 把处理信息返回到客户端
                        stream.Write(returnByteArr, 0, returnByteArr.Length);
                        ShowMsg($"HTTP请求响应内容:{returnObj}");
                    }
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"发生异常:{ex.ToString()}");
                    ShowMsg($"发生异常:{ ex.ToString()}");
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"发生异常:{ex.ToString()}");
                ShowMsg($"发生异常:{ ex.ToString()}");
            }
        }

        private string HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            // 获取请求参数
            NameValueCollection myCol = request.QueryString;

            var contentType = request.ContentType;

            try
            {
                // 获取Post请求中的参数和值帮助类
                HttpListenerPostParaHelper httppost = new HttpListenerPostParaHelper(request);
                // 获取Post过来的参数和数据
                List<HttpListenerPostValue> lst = httppost.GetHttpListenerPostValue();

                var data = "";
                // 获取body中的参数
                foreach (var key in lst)
                {
                    if (key.type == 0)
                    {
                        string value = Encoding.UTF8.GetString(key.datas).Replace("\r\n", "");
                        if (key.name == "QUERY_STRING") // 参数名
                        {
                            data = value;
                            Console.WriteLine(value);
                        }
                    }
                }

                response.StatusDescription = "200"; // 获取或设置返回给客户端的 HTTP 状态代码的文本说明。
                response.StatusCode = 200; // 获取或设置返回给客户端的 HTTP 状态代码。
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine($"接收数据完成:{data.Trim()},时间:{DateTime.Now.ToString()}");
                ShowMsg($"接收数据完成:{data.Trim()}");

                // 获取得到数据data可以进行其他操作

                return $"接收数据完成";
            }
            catch (Exception ex)
            {
                response.StatusDescription = "404";
                response.StatusCode = 404;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"在接收数据时发生错误:{ex.ToString()}");
                return $"在接收数据时发生错误:{ex.ToString()}"; // 把服务端错误信息直接返回可能会导致信息不安全,此处仅供参考
            }
        }

        private void btn_开启HTTP监听_Click(object sender, EventArgs e)
        {
            if (httpListener == null)
            {
                httpListener = new HttpListener();
                httpListener.Prefixes.Add($"{txt_接收端地址.Text.Trim()}"); // http://xxx.xxx.xxx.xxx:8082/base/saveData/
                httpListener.Start();
                httpListener.BeginGetContext(new AsyncCallback(GetHttpListenerCallBack), httpListener);
                ShowMsg($"{txt_接收端地址.Text.Trim()} HTTP监听已开启");
            }
        }

        private delegate void dlgShowMsg(string msg);

        private void ShowMsg(string msg)
        {
            if (richTextBox1.InvokeRequired)
            {
                dlgShowMsg dlg = new dlgShowMsg(ShowMsg);
                richTextBox1.Invoke(dlg, msg);
            }
            else
            {
                if (richTextBox1.Lines.Length >= 1000)
                    richTextBox1.Clear();
                richTextBox1.AppendText($"{Environment.NewLine}{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}        {msg}");
            }
        }

        private void btn_清空HTTP日志_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }
    }
}

解析POST请求中的参数,写了一个 HttpListenerPostParaHelper 帮助类,代码如下:

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
 * 版权所有 (c) 2021  保留所有权利。
 * CLR版本:4.0.30319.42000
 * 机器名称:DESKTOP-T90SFH8
 * 公司名称:
 * 命名空间:HttpListenerDemo
 * 唯一标识:a871efaa-2645-4503-bc99-8e05369ba4c9
 * 文件名:HttpListenerPostParaHelper
 * 当前用户域:DESKTOP-T90SFH8
 *
 * 创建者:Cgs
 * 电子邮箱:1003590782@qq.com
 * 创建时间:10/14/2021 9:40:45 AM
 * 版本:V1.0.0
 * 描述:
 *
 * ----------------------------------------------------------------
 * 修改人:
 * 时间:
 * 修改说明:
 *
 * 版本:V1.0.1
 *----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace HttpListenerDemo
{
    /// <summary>
    /// HttpListenerPostParaHelper 的摘要说明
    /// </summary>
    internal class HttpListenerPostParaHelper
    {
        #region <变量>

        private HttpListenerRequest request;

        #endregion <变量>

        #region <方法>

        public HttpListenerPostParaHelper(HttpListenerRequest request)
        {
            this.request = request;
        }

        private bool CompareBytes(byte[] source, byte[] comparison)
        {
            try
            {
                int count = source.Length;
                if (source.Length != comparison.Length)
                    return false;
                for (int i = 0; i < count; i++)
                    if (source[i] != comparison[i])
                        return false;
                return true;
            }
            catch
            {
                return false;
            }
        }

        private byte[] ReadLineAsBytes(Stream SourceStream)
        {
            var resultStream = new MemoryStream();
            while (true)
            {
                int data = SourceStream.ReadByte();
                resultStream.WriteByte((byte)data);
                if (data == 10)
                    break;
            }
            resultStream.Position = 0;
            byte[] dataBytes = new byte[resultStream.Length];
            resultStream.Read(dataBytes, 0, dataBytes.Length);
            return dataBytes;
        }

        /// <summary>
        /// 获取Post过来的参数和数据
        /// </summary>
        /// <returns></returns>
        public List<HttpListenerPostValue> GetHttpListenerPostValue()
        {
            try
            {
                List<HttpListenerPostValue> HttpListenerPostValueList = new List<HttpListenerPostValue>();
                if (request.ContentType.Length > 20 && string.Compare(request.ContentType.Substring(0, 20), "multipart/form-data;", true) == 0)
                {
                    string[] HttpListenerPostValue = request.ContentType.Split(';').Skip(1).ToArray();
                    string boundary = string.Join(";", HttpListenerPostValue).Replace("boundary=", "").Trim();
                    byte[] ChunkBoundary = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
                    byte[] EndBoundary = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
                    Stream SourceStream = request.InputStream;
                    var resultStream = new MemoryStream();
                    bool CanMoveNext = true;
                    HttpListenerPostValue data = null;
                    while (CanMoveNext)
                    {
                        byte[] currentChunk = ReadLineAsBytes(SourceStream);
                        if (!Encoding.UTF8.GetString(currentChunk).Equals("\r\n"))
                            resultStream.Write(currentChunk, 0, currentChunk.Length);
                        if (CompareBytes(ChunkBoundary, currentChunk))
                        {
                            byte[] result = new byte[resultStream.Length - ChunkBoundary.Length];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            CanMoveNext = true;
                            if (result.Length > 0)
                                data.datas = result;
                            data = new HttpListenerPostValue();
                            HttpListenerPostValueList.Add(data);
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
                        }
                        else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Disposition"))
                        {
                            byte[] result = new byte[resultStream.Length - 2];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            CanMoveNext = true;
                            data.name = Encoding.UTF8.GetString(result).Replace("Content-Disposition: form-data; name=\"", "").Replace("\"", "").Split(';')[0];
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
                        }
                        else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Type"))
                        {
                            CanMoveNext = true;
                            data.type = 1;
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
                        }
                        else if (CompareBytes(EndBoundary, currentChunk))
                        {
                            byte[] result = new byte[resultStream.Length - EndBoundary.Length - 2];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            data.datas = result;
                            resultStream.Dispose();
                            CanMoveNext = false;
                        }
                    }
                }
                return HttpListenerPostValueList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        #endregion <方法>
    }

    /// <summary>
    /// HttpListenner监听Post请求参数值实体
    /// </summary>
    public class HttpListenerPostValue
    {
        /// <summary>
        /// 0:参数
        /// 1:文件
        /// </summary>
        public int type = 0;

        public string name;
        public byte[] datas;
    }
}

3.下载例程

该例程演示了HttpListener、HttpWebRequest的应用,包括如何解析POST请求中Body的数据(multipart/form-data)、如何构造multipart/form-data; boundary=的ContentType等进行文件、参数上传等技巧:https://download.csdn.net/download/CGS_______/33070416
在这里插入图片描述

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 12:07:43  更:2021-10-15 12:08:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:37:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码