极客秀
搜索

基于C#的软件大杂烩(5.1)——简介HTTP协议以及编写HTTP服务端

上一期我们介绍了使用TCP协议来建立流式传输实现实时的图像显示。我们也简单的提到了HTTP与TCP协议的优缺点。
本期我们简单的介绍一下HTTP并且使用C#制作一个HTTP助手来接收我们的HTTP消息。
HTTP简介 HTTP是超文本传输协议( Hypertext Transfer Protocol )的简称,既然是一种协议,HTTP分为
客户端和服务端 ,顾名思义服务端是为客户端服务的。 服务端不会主动发送请求,但是服务端可以响应客服端发出的请求
客户端通过请求报文向服务端发送消息,服务端接收到请求报文后会使用响应报文对客户端进行响应,HTTP规定了请求报文和响应报文的格式。 HT
TP请求报文如下所示 <请求方法>
| <请求路劲 > | <版本 >
—|—|—
<请求内容>….

GET https://pic.qr2c.cn/1.1......

例如这个例子,请求方法是GET,请求路劲是https://pic.qr2c.cn/1.1

HTTP响应报文如下所示 <版本>
| <状态码 > | <原因 >
—|—|—
<响应内容>

HTTP/1.1 200 OK.......

200通常代表着响应成功。

其实关于HTTP还有好多好多内容,我们就简单的介绍一下HTTP的请求和响应机制,接着使用C#编写测试代码。

界面布局

还是简单的布置一下我们的界面,使用一个TextBox来接收客户端发送的请求报文,下面设置一个我们的自定义响应文本。

右边使用Comombox控件来存放电脑的可用IP地址,并且可以选择输入端口号。

设置波形显示的勾选框,方便后期可以从HTTP协议中解析波形。

设置详细信息的勾选框,可以选择显示详细信息还是显示简短的信息。

主要代码 ****


        private void LoadLocalIPv4Addresses()        {            try            {                // 获取本地主机名                string hostName = Dns.GetHostName();                // 获取主机名对应的IP地址列表                IPAddress[] ipAddresses = Dns.GetHostAddresses(hostName);                // 筛选IPv4地址并添加到ComboBox                foreach (IPAddress ipAddress in ipAddresses.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork))                {                    IPAddressChoose.Items.Add(ipAddress.ToString());                }  
                // 设置默认选择第一个IPv4地址                if (IPAddressChoose.Items.Count > 0)                {                    IPAddressChoose.SelectedIndex = 0;                }            }            catch (Exception ex)            {                MessageBox.Show($"错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            }        }

利用Dns.GetHostName的方法获得主机的可用IP地址,并将地址写入名为IPAddressChoose的Comombox控件中

需要注意的是传入格式的问题IPAddresses是IPAddress类型的数据,我们需要将其转换为IPAddress类型传入IPAddressChoose控件的Text属性中。


        private HttpListener httpListener = null;        private void CreateHttpListener()        {            try            {                httpListener = new HttpListener();                // 获取选择的 IP 地址和端口号                string selectedIpAddress = IPAddressChoose.SelectedItem.ToString();                string selectedPort = PortChoose.Text;  
                // 创建监听地址                string listenUrl = $"https://pic.qr2c.cn/";  
                // 创建 HttpListener 实例                httpListener.Prefixes.Add(listenUrl);  
                // 启动监听器                try                {                    // 启动监听器                    httpListener.Start();                    IPAddressChoose.Enabled = true;                    PortChoose.Enabled = true;                    // 异步处理接收请求                    Task.Run(async () =>                    {                        while (true)                        {                            // 等待请求连接                            HttpListenerContext context = await httpListener.GetContextAsync();  
                            // 处理请求                            HandleHttpRequest(context);                        }                    });                }                catch (HttpListenerException ex)                {                    // 输出错误信息或采取适当的处理措施                    MessageBox.Show("访问端口失败rn如未启动管理员模式请使用管理员模式启动rn检查端口是否被占用可以尝试更换端口");                }            }            catch (Exception ex)            {                MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);            }        }  
        private void HandleHttpRequest(HttpListenerContext context)        {            // 获取请求对象            HttpListenerRequest request = context.Request;  
            // 获取请求的 URL            string url = request.Url.AbsoluteUri;  
            // 获取请求的 HTTP 方法(GET、POST 等)            string httpMethod = request.HttpMethod;  
            // 获取请求头            WebHeaderCollection headers = request.Headers as WebHeaderCollection;  
            // 获取请求的 IP 地址            string ipAddress = context.Request.RemoteEndPoint?.Address?.ToString();  
            // 读取请求正文            string requestBody;            using (System.IO.Stream body = request.InputStream)            using (System.IO.StreamReader reader = new System.IO.StreamReader(body, request.ContentEncoding))            {                requestBody = reader.ReadToEnd();            }  
            // 在这里处理请求正文            this.BeginInvoke(new Action(() =>            {                // 显示 IP 地址                if (!ChartShow.Checked)                {                    Recive.AppendText("New Message:rn");  
                    Recive.AppendText($"IP Address: {ipAddress}rn");  
                    // 显示 URL                    Recive.AppendText($"URL: {url}rn");                }                if (MoreDetile.Checked&&!ChartShow.Checked)                {  
                    // 显示 HTTP 方法                    Recive.AppendText($"HTTP Method: {httpMethod}rn");  
                    // 显示请求头                    Recive.AppendText($"Request Headers:n{string.Join("n", headers.AllKeys.Select(key => $"{key}: {headers[key]}"))}rn");  
                    // 显示请求正文                    Recive.AppendText($"Request Body:n{requestBody}rn");                }                else                {                    Dictionary<string, string> keyValuePairs = ParseJsonRequestBody(requestBody);  
                    // 在这里处理请求正文                    this.BeginInvoke(new Action(() =>                    {                        // 打印键值对                        foreach (var kvp in keyValuePairs)                        {                            if (double.TryParse(kvp.Value, out double doubleValue))                            {                                if (ChartShow.Checked)                                {                                    // 在 Chart 中检查是否包含对应键名的 Serial                                    if (chart.Series.Any(series => series.Name == kvp.Key))                                    {                                        // 如果已经包含,将数据添加到对应的 Serial 中                                        chart.Series[kvp.Key].Points.AddXY(chart.Series[kvp.Key].Points.Count+1, double.Parse(kvp.Value));                                    }                                    else                                    {                                        // 如果不存在,新建对应键名的 Serial,并添加数据                                        Series newSeries = new Series(kvp.Key);                                        Random random = new Random();                                        Color randomColor = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256));  
                                        // 新建 Series,并设置线条的属性  
                                        newSeries.Color = randomColor;  // 设置颜色                                        newSeries.BorderWidth = 3;      // 设置宽度                                        newSeries.ChartType = SeriesChartType.Spline;                                        newSeries.Points.AddY(double.Parse(kvp.Value));                                        chart.Series.Add(newSeries);                                    }                                }                            }                            Recive.AppendText($"{kvp.Key}: {kvp.Value}rn");                        }  
                    }));                }  
            }));  
            // 构建响应内容            string responseString = Recall.Text;            byte[] buffer = Encoding.UTF8.GetBytes(responseString);  
            // 发送响应            HttpListenerResponse response = context.Response;            response.ContentLength64 = buffer.Length;            System.IO.Stream output = response.OutputStream;            output.Write(buffer, 0, buffer.Length);            output.Close();        }

接着初始化一个监听实例,根据我们选择的IP地址以及端口号创建HTTP监听,并通过异步的方式处理接收到的数据,将数据打印或者从中解析出波形显示在外面的页面上。

** 效果展示 **

使用HTTP客户端工具来测试接收代码。

可以看到无论是接收数据,还是数据解析都是成功的,之后就是需要我们不停的完善代码。

1.转载请保留原文链接谢谢!
2.本站所有资源文章出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
3.本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户擦亮眼睛自行鉴别,做一个有主见和判断力的用户。
4.本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。
5.联系方式(#替换成@):pm#vimge.com

  相关内容