C#通讯——关于Winform中的简单的Http服务器与客户端

C#通讯——关于Winform中的简单的Http服务器与客户端

  • 前言
  • 一、Http是什么?
  • 二、简单的Http服务器
  • 三、简单的Http客户端
  • 四、实际调用
  • 五、Winform中Http服务器和WebApi的区别?


前言

在实际项目中通讯的交互的过程中,遇见数据传输时同事和我说用WebApi,Get,Post等等,以前没用搞过这个块的我傻傻分不清。查询资料了解过后发现只是个简单的Http交互通讯,在此记录下Winform中的简单服务器和客户端的编写,并简要描述webapi与http通讯的差异。


一、Http是什么?

HTTP(Hypertext Transfer Protocol)是一种用于在网络上传输超文本的协议。它是一个用于传输和交换超文本、图像、视频、音频以及其他多媒体资源的应用层协议。

HTTP是Web的基础,它定义了客户端和服务器之间的通信规则。通常,当你在浏览器中输入网址、点击链接或者提交表单时,浏览器会发送HTTP请求到服务器,服务器收到请求后进行处理,然后返回HTTP响应给客户端(浏览器),最终在你的浏览器上显示网页内容。

HTTP协议的主要特点包括:

  • 无状态性(Stateless):
    HTTP协议本身是无状态的,每个请求都是相互独立的,服务器并不会保留前后请求之间的状态信息。这导致每个请求都需要包含足够的信息来被服务器正确处理,比如会话标识或者其他验证信息。
  • 基于请求-响应模型:
    客户端发送请求给服务器,服务器处理请求并返回响应。这个请求-响应模型是HTTP的核心概念,通过这种方式客户端能够请求不同资源并且服务器能够提供响应。
  • 支持多种请求方法:
    HTTP定义了一系列请求方法(也称为HTTP谓词),包括GET(用于获取资源)、POST(用于提交数据给服务器)、PUT(用于更新资源)、DELETE(用于删除资源)等。
  • URL定位资源:
    每个HTTP请求都包含一个URL(Uniform Resource Locator),用于指定被请求的资源的位置。
  • 无连接性:
    HTTP协议本身是无连接的,即每次请求完成后,连接会立即关闭。这意味着每个请求都需要重新建立连接,可能会造成一定的性能开销。

二、简单的Http服务器

using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;namespace httpServer
{class HttpServer_DP{private readonly string mUrl; // 服务器监听的URLprivate readonly HttpListener mListener; // HttpListener实例private readonly Dictionary<string, Func<HttpListenerContext, Task<string>>> mRoutes; // 路由映射// 构造函数,接收服务器监听地址和端口的数组public HttpServer_DP(string[] prefixes){if (!HttpListener.IsSupported){throw new NotSupportedException("HttpListener is not supported on this platform.");}mListener = new HttpListener(); // 初始化HttpListener实例mRoutes = new Dictionary<string, Func<HttpListenerContext, Task<string>>>(); // 初始化路由映射字典// 为服务器添加监听地址和端口foreach (string prefix in prefixes){mListener.Prefixes.Add(prefix);}mUrl = prefixes[0]; // 记录第一个监听地址}public bool IsOpen { get { return mListener.IsListening; } }// 启动服务器public void Start(){mListener.Start();Console.WriteLine($"Server started and listening on {mUrl}");mListener.BeginGetContext(ProcessRequestCallback, mListener); // 处理客户端请求}// 停止服务器public void Stop(){mListener.Stop();mListener.Close();Console.WriteLine("Server stopped.");}// 添加路由和处理程序的映射关系public void AddRoute(string route, Func<HttpListenerContext, Task<string>> handler){mRoutes.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 responseString = "No Data!"; // 默认响应字符串string url = context.Request.Url.AbsolutePath;Func<HttpListenerContext, Task<string>> handler;// 如果请求路径存在于路由映射中,执行相应的处理程序if (mRoutes.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;// 将响应写入输出流并关闭输出流context.Response.OutputStream.Write(buffer, 0, buffer.Length);context.Response.OutputStream.Close();}else{// 如果请求路径不存在于路由映射中,返回404 Not Foundcontext.Response.StatusCode = (int)HttpStatusCode.NotFound;context.Response.Close();}}catch (Exception ex){Console.WriteLine($"Error processing request: {ex.Message}");}}}
}

需要注意的是:Dictionary<string, Func<HttpListenerContext, Task>> mRoutes; // 路由映射
为了方便根据客户端传入的URL的不同路径来选择进行不同的处理流程

三、简单的Http客户端

using System;
using System.Net.Http;
using System.Threading.Tasks;namespace Http
{class HttpClient_DP{private readonly HttpClient _client; // HttpClient 实例// 构造函数,初始化 HttpClient 实例public HttpClient_DP(){_client = new HttpClient();}// 设置超时时间public TimeSpan TimeOut { set { _client.Timeout = value; } }// 发送 GET 请求并返回响应内容public async Task<string> Get(string url){HttpResponseMessage response = await _client.GetAsync(url); // 发送 GET 请求if (response.IsSuccessStatusCode){string content = await response.Content.ReadAsStringAsync(); // 读取响应内容return content;}else{return $"Error: {response.StatusCode}"; // 返回错误信息}}// 发送 POST 请求并返回响应内容public async Task<string> Post(string url, string data){HttpContent content = new StringContent(data); // 创建包含请求数据的 HttpContent 实例HttpResponseMessage response = await _client.PostAsync(url, content); // 发送 POST 请求if (response.IsSuccessStatusCode){string responseData = await response.Content.ReadAsStringAsync(); // 读取响应内容return responseData;}else{return $"Error: {response.StatusCode}"; // 返回错误信息}}}
}

其中只实现的Get与Post的相关代码,这也是当前我最常用的两个方法。
其中 public TimeSpan TimeOut为超时时间,不设置时将永久等待服务器响应。当响应超时时,外部可以通过(try-catch)捕获TaskCanceledException异常。

四、实际调用

初始化服务器:

        httpServer.HttpServer_DP HttpServer;public static void IniHttpServer(){HttpServer = new httpServer.HttpServer_DP(new string[]{"http://127.0.0.1:8080/"});//绑定映射,处理函数//当传入URL为"http://127.0.0.1:8080/PostAGVC_Data/"时将调用PostAGVC_Data函数接收和解析HttpServer.AddRoute("/PostAGVC_Data/", PostAGVC_Data);//当传入URL为"http://127.0.0.1:8080/PostAGV_Data/"时将调用PostAGV_Data函数接收和解析HttpServer.AddRoute("/PostAGV_Data/", PostAGV_Data);HttpServer.Start();}public static async Task<string> PostAGVC_Data(HttpListenerContext context){string httpMethod = context.Request.HttpMethod;string responseString = "";// 处理 POST 请求if (context.Request.HasEntityBody){// 从请求主体中获取数据using (System.IO.Stream body = context.Request.InputStream){using (System.IO.StreamReader reader = new System.IO.StreamReader(body, context.Request.ContentEncoding)){string postData = reader.ReadToEnd(); // 读取 POST 数据//处理数据//。。。。。。。。。。。。//。。。。。。。。。。。。//返回字符串responseString = "OK";}}}return responseString;}//与PostAGVC_Data内部类似,处理数据的代码不一样public static async Task<string> PostAGV_Data(HttpListenerContext context){//省略}

由于Http的无连接性,客户端只需要实例化后,需要时进行连接就行,简单的初始化(如果需要的话)如下:

		Http.HttpClient_DP HttpClient ;public static void IniHttpClient(){if (HttpClient == null){HttpClient = new Http.HttpClient_DP();HttpClient.TimeOut = TimeSpan.FromSeconds(10);}}

调用:
其中JsonConvert只是将我的类实例序列化成Json字符串,在此可以仅当字符串来看。

        string ret = await Global_Value.HttpClient.Post(url, JsonConvert.SerializeObject(new PLC_WorkState(){name = agvName,workState = workState}));

要注意一个问题,在不是本地回环地址(127.0.0.1)时,服务器启动会存在积极拒绝的情况,此时需要用管理员权限去打开应用程序或者是VS平台。

五、Winform中Http服务器和WebApi的区别?

在WinForms中编写的HTTP服务器类与WebAPI之间有几个主要区别:

1.目的和设计用途:

  • WinForms HTTP服务器类:
    通常是基于Socket或其他网络库手动实现的简单HTTP服务器。这样的服务器可能是为了特定目的而创建,比如在本地进行简单的通信或提供特定服务。
  • WebAPI: 是一个在Web开发中常用的框架,用于构建基于HTTP的RESTful
    API。它是ASP.NET框架的一部分,提供了更完整、功能更丰富的API开发环境,包括路由、中间件、控制器、模型绑定等。

2.功能和特性:

  • WinForms HTTP服务器类:
    往往具有较少的功能,可能只实现了基本的HTTP请求/响应处理,而缺少高级特性和工具。它通常用于较小规模的需求。
  • WebAPI:
    提供了许多功能强大的特性,例如路由,HTTP谓词(GET、POST、PUT等)的自动映射到相应的处理方法,参数绑定、模型验证等,使得开发者能够更轻松地构建和管理API。

3.集成和扩展性:

  • WinForms HTTP服务器类: 通常需要手动处理连接、请求、响应和其他网络层细节,灵活性较高,但也需要开发者自行处理许多功能。
  • WebAPI:
    集成在ASP.NET中,可以利用ASP.NET提供的丰富特性和中间件,容易与其他ASP.NET组件集成,并且具有更强的扩展性。

4.适用场景:

  • WinForms HTTP服务器类: 适用于需要在WinForms应用程序中实现简单的HTTP通信或提供基本服务的情况。

  • WebAPI: 更适合构建大型的Web应用程序或服务,提供多种HTTP服务,满足各种复杂的需求,例如构建RESTfulAPI供移动应用或Web前端使用。

总体来说,WinForms中的简单HTTP服务器类适用于简单的、局部的HTTP通信需求,而WebAPI更适用于构建和管理完整的Web服务或RESTful API,并提供了更多现成的工具和功能来简化开发流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/581891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读《Rethinking Efficient Lane Detection via Curve Modeling》

目录 Abstract 1. Introduction 2. Related Work 3. BezierLaneNet 3.1. Overview 3.2. Feature Flip Fusion 3.3. End-to-end Fit of a Bezier Curve 4. Experiments 4.1. Datasets 4.2. Evalutaion Metics 4.3. Implementation Details 4.4. Comparisons 4.5. A…

使用克魔助手进行iOS数据抓包和HTTP抓包的方法详解

摘要 本文博客将介绍如何在iOS环境下使用克魔助手进行数据抓包和HTTP抓包。通过抓包&#xff0c;开发者可以分析移动应用程序的网络请求发送和接收过程&#xff0c;识别潜在的性能和安全问题&#xff0c;提高应用的质量和安全性。 引言 在移动应用程序的开发和测试过程中&am…

Linux磁盘与文件系统管理

目录 在linux系统中使用硬盘 磁盘的数据结构 磁盘接口类型 字母含义 MBR磁盘分区 分区类型 分区的缺点 文件系统的 文件系统有什么作用 文件系统的修复 检测并确认新磁盘 参看磁盘信息 查看磁盘信息 添加磁盘 查看添加磁盘情况&#xff1a;sda系统磁盘&#xff…

每周一算法:区间覆盖

问题描述 给定 N N N个闭区间 [ a i , b i ] [a_i,b_i] [ai​,bi​]&#xff0c;以及一个线段区间 [ s , t ] [s,t] [s,t]&#xff0c;请你选择尽量少的区间&#xff0c;将指定线段区间完全覆盖。 输出最少区间数&#xff0c;如果无法完全覆盖则输出 − 1 -1 −1。 输入格式…

【自然语言处理】第3部分:识别文本中的个人身份信息

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

凸函数的定义,保凸运算和各种性质

定义: 函数 f : R n → R f:R^n\rightarrow R f:Rn→R是凸的,如果 d o m f domf domf是凸集,且对于任意 x , y ∈ d o m f x,y\in domf x,y∈domf和任意 0 ≤ θ ≤ 1 0\le \theta \le1 0≤θ≤1都有 f ( θ x ( 1 − θ ) y ) ≥ θ f ( x ) ( 1 − θ ) f ( y ) f(\theta x…

解决Hive在DataGrip 中注释乱码问题

注释属于元数据的一部分&#xff0c;同样存储在mysql的metastore库中&#xff0c;如果metastore库的字符集不支持中文&#xff0c;就会导致中文显示乱码。 不建议修改Hive元数据库的编码&#xff0c;此处我们在metastore中找存储注释的表&#xff0c;找到表中存储注释的字段&a…

软件测试/测试开发丨Python学习笔记之基本数据类型与操作

一、变量 1、变量的定义&#xff1a; a. 在python中&#xff0c;变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间&#xff1b; b.变量的值可以被读取和修改。 2、命名规则&#xff1a; a.变量名由字母&#xff08;广义的Unic…

Python 常用模块Logging

Python 常用模块Logging 【序言】 logging模块是专门用来做日志记录的模块 【一】日志等级 默认打印结果到终端上 CRITICAL 50 # 致命错误 ERROR 40 # 错误 WARNING 30 # 警告 INFO 20 # 消息 DEBUG 10 # 调试 NOTSET 0 # 不设置示例&#xff1a; 默认级别为…

Unity引擎有哪些优点

Unity引擎是一款跨平台的游戏引擎&#xff0c;拥有很多的优点&#xff0c;如跨平台支持、强大的工具和编辑器、灵活的脚本支持、丰富的资源库和强大的社区生态系统等&#xff0c;让他成为众多开发者选择的游戏开发引擎。下面我简单的介绍一下Unity引擎的优点。 跨平台支持 跨…

自动化网络故障修复管理

什么是故障管理 故障管理是网络管理的组成部分&#xff0c;涉及检测、隔离和解决问题。如果实施得当&#xff0c;网络故障管理可以使连接、应用程序和服务保持在最佳水平&#xff0c;提供容错能力并最大限度地减少停机时间。专门为此目的设计的平台或工具称为故障管理系统。 …

WPF实战项目二十二(客户端):首页添加备忘录与待办事项

1、在View文件夹下新建文件夹Dialog&#xff0c;新建View&#xff1a;AddMemoView、AddToDoView <UserControlx:Class"WPFProject.Views.Dialogs.AddToDoView"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…

推荐五款简洁而实用的工具,值得你尝试

​ 分享快乐是生活中美好的瞬间&#xff0c;而分享简单巧妙的工具也能令我愉悦。这五款工具简洁而实用&#xff0c;值得你尝试。 1.视频播放器——Potplayer Potplayer是一款视频播放器&#xff0c;支持DXVA、CUDA和QuickSync等硬件加速技术&#xff0c;提供高效的视频播放性…

Linux(openssl):用CA证书签名具有SAN的CSR

Linux(openssl):创建CA证书,并用其对CSR进行签名_生成ca证书签名请求文件csr-CSDN博客 提供了方法为CSR进行签名。 对于有SAN的CSR如何签名呢? 1.创建CA证书,与下面的帖子一样

关于Java并发、JVM面试题

前言 之前为了准备面试&#xff0c;收集整理了一些面试题。 本篇文章更新时间2023年12月27日。 最新的内容可以看我的原文&#xff1a;https://www.yuque.com/wfzx/ninzck/cbf0cxkrr6s1kniv 并发 进程与线程的区别 线程属于进程&#xff0c;进程可以拥有多个线程。进程独享…

【论文阅读】Resource Allocation for Text Semantic Communications

这是一篇关于语义通信中资源分配的论文。全文共5页&#xff0c;篇幅较短。 目录在这里 摘要关键字引言语义通信资源分配贡献公式符号 系统模型DeepSC TransmitterTransmission ModelDeepSC Receiver 语义感知资源分配策略Semantic Spectral Efficiency &#xff08;S-SE&#…

C++初阶(十七)模板进阶

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、非类型模板参数二、模板的特化1、概念2、函数模板特化3、类模板特化1、全特化2、偏特化 三…

Python爬虫篇(四):京东数据批量采集

京东数据批量采集 ●前言 一年一度的端午节又到了&#xff0c;甜咸粽子之争也拉开了帷幕&#xff0c;它价格高昂&#xff0c;它味道鲜美&#xff0c;然而&#xff0c;默默无名的它却备受广大民众喜爱&#xff01;好家伙&#xff0c;一看就是老qq看点了 &#xff0c;那咱们能做…

07.kubernetes客户端部署

kubernetes 客户端部署 主要是配置 kubectl 完成以下两个操作: 首先是要实现通过命令行连接到Kubernetes的apiserver然后就是创建必要的 ClusterRoleBinding 实现 kubelet bootstrapping CSR 的自动验签kubelet bootstrapping主要涉及以下两个问题,官方文档已经给出详细的介…

Flink1.17实战教程(第七篇:Flink SQL)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…