当前位置: 首页 > article >正文

C# Http Post 长连接和短连接请求

  • 概述

HTTP是建立在TCP/IP协议之上的应用层协议。最常用的就是get 和 post请求,它们最早被用来做浏览器与服务器之间交互HTML和表单的通讯协议,后来又被广泛的扩充到接口格式的定义上,到目前为止,get / post 请求依然应用在各大网站中,比如在用户登录时、向服务器提交表单数据等。http 协议是基础,但也是重点,我们必学的。

  • Post请求与 Get的区别

1、数据传输方式的区别

Get请求:将请求的数据以字符串的形式附加在URL后面,通过URL传递给服务器。

Post请求:将请求的数据放在请求体中传输给服务器。

2、数据传输安全性的区别

GET请求:由于参数数据是以明文形式传输的,会暴露在URL上,不适合传输敏感数据。

POST请求:由于数据是以请求体传输的,相对安全,相对安全些。

3、数据传输长度的区别

GET请求:由于数据是附加在URL中传输的,有长度限制,GET请求传输的数据量较小,大小限制通常为2048字符。

POST请求:由于数据是放在请求体中传输的,数据量没有限制。

4、用途区别

GET请求:用于从服务器检索数据,可以缓存上次的请求。

POST请求:用于向服务器提交数据,没有缓存。

  • 具体实现

代码平台:Visual Studio 2019

项目类型:C# 控制台应用程序

短连接请求:

/*
 * 功能:Http Post 短连接请求
 * 作者:WangYadong
 * 日期:2024/11/14
 * 
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace HttpServerTest
{
    public class HttpPost
    {
        public static string zongJueData;
        private string url = "http://xxxxx/xxxx"; //url地址

        //private HttpWebRequest request;
        //public void InitHttpPost()
        //{
        //    request = (HttpWebRequest)WebRequest.Create(url);
        //    request.Method = "POST";
        //    request.ContentType = "application/x-www-form-urlencoded"; //用于浏览器的<form>表单的请求(这是默认的数据提交格式)
        //    request.Connection = "keep-alive";  //长连接,待定
        //}


        /// <summary>
        /// Http Post请求数据
        /// </summary>
        /// <param name="sender">这个参数是Timer(计时器)需要的结构参数</param>
        /// <param name="e">这个参数是Timer(计时器)需要的结构参数</param>
        public void HttpPostData(object sender, ElapsedEventArgs e)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded"; //用于浏览器的<form>表单的请求(这是默认的数据提交格式)

            //request.ContentType = "multipart/form-data"; //当需要在表单中传输文件时,通常会使用这种格式
            //request.ContentType = "application/json"; //当发送 JSON 数据时,通常会使用这种格式
            //request.ContentType = "text/xml"; //当发送 XML 数据时,通常会使用这种格式

            //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");

            //添加参数(添加在post请求的body中)
            StringBuilder builder = new StringBuilder();
            builder.Append("&");
            builder.AppendFormat("{0}={1}", "userCode", "xxxxxxxxxx"); //参数数据

            //将请求体内容写入流中
            byte[] paramJsonBytes;
            paramJsonBytes = Encoding.ASCII.GetBytes(builder.ToString());
            request.ContentLength = paramJsonBytes.Length;
            Stream writer = request.GetRequestStream();
            writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
            writer.Close();

            //发送请求
            var response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                var result = string.Empty;
                //使用流接收数据
                using (var streamReader = new StreamReader(response.GetResponseStream()))
                {
                    //读取流中的内容
                    result = streamReader.ReadToEnd();
                    //JSON序列化,返回JToken对象
                    var resJson = JToken.Parse(result);
                    var code = Convert.ToInt32(resJson["code"]);
                    if (code != 200)
                    {
                        zongJueData = "";
                        Console.WriteLine("数据请求失败!");
                        return;
                    }
                    Console.WriteLine(resJson);
                }
            }
            else
            {
                Console.WriteLine("无效请求!");
                zongJueData = "";
            }
        }
    }
}

request.Method = "POST" :明确了Post请求

HTTP中的Content-Type(内容类型),用于定义网络文件的类型和网页的编码方式,让数据接收方决定以什么形式、什么编码读取这个文件。 

 request.ContentType = "application/x-www-form-urlencoded"; 明确了请求格式是浏览器的<form>表单的请求

其他格式还有:

request.ContentType = "multipart/form-data":当需要在表单中传输文件时,通常会使用这种格式
request.ContentType = "application/json":当发送 JSON 数据时,通常会使用这种格式
request.ContentType = "text/xml":当发送 XML 数据时,通常会使用这种格式

参数数据添加在post请求的body中: 

StringBuilder builder = new StringBuilder();

builder.Append("&");
builder.AppendFormat("{0}={1}", "userCode", "412721199303215033");  //参数数据

//将请求体内容写入流中

byte[] paramJsonBytes;
paramJsonBytes = Encoding.ASCII.GetBytes(builder.ToString());
request.ContentLength = paramJsonBytes.Length;

Stream writer = request.GetRequestStream();

writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
writer.Close();

以上是 短连接。

有同学会有持续请求的需求,比如:需要每隔1秒(或者更频繁)向服务器请求数据,以保证数据实时在界面上更新显示。那这种情况短连接就不适用了,因为短连接每次都需要建立新连接,然后向服务器发送请求,拿到数据后再断开,下次再重复此操作。这样比较费资源,简单的数据请求可以支持,但如果数据量繁重的情况下怎么办呢?这会给电脑造成很重的负担,这时就需要长连接进行请求了。

长连接请求:

所谓长连接就是只建立一次连接后,不断开,下次进行数据请求时直接发送参数即可

长连接与短接的区别就在于在请求头中设置Connectionkeep-alive,只需要这一句代码即可

/*
 * 功能:Http Post 短连接请求
 * 作者:WangYadong
 * 日期:2024/11/14
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Web;

namespace HttpServerTest
{
    public class HttpPostLongConn
    {
        public static HttpClient httpClient;
        private string url = "http://xxxxxx/xxxxxx"; //url地址
        // 参数
        private static Dictionary<string, string> parameters = new Dictionary<string, string> { { "userCode", "xxxxxxxxxx" } };

        public void InitHttp()
        {
             httpClient = new HttpClient() { BaseAddress=new Uri(url) };
            // 设置HttpClientHandler以允许长连接
            httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");
            //设置连接超时时间,超过3秒就断开(由于是长连接,所以这主要是告诉服务器,超过这个时间就断开,不然服务器持续保持连接,客户端多了它负担就很大)
            httpClient.Timeout = new TimeSpan(0,0,0,3);
        }
        public async void HttpReqData(object sender, ElapsedEventArgs e)
        {
            // 发送请求
            FormUrlEncodedContent content = new FormUrlEncodedContent(parameters); //创建FormUrlEncodedContent参数
            HttpResponseMessage response = await httpClient.PostAsync("", content);
            string contentRes = await response.Content.ReadAsStringAsync();
            Console.WriteLine(contentRes.Substring(0, contentRes.Length));
        }
    }
}

        private static Dictionary<string, string> parameters = new Dictionary<string, string> { { "userCode", "xxxxxxxxxx" } };就是请求参数 

 httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");  这行代码就是设置长连接

  httpClient.Timeout = new TimeSpan(0,0,0,3); 是设置连接超时时长,这个主要是给服务器端设置的,告诉服务端该客户端请求超过这个时长就断开。对于客户端来说持续保持长连接可以承受,但对于服务器来说压力就太大了,所以对连接超时的客户端适时中断可以缓解服务器压力

将参数放到方法体中: 

  FormUrlEncodedContent content = new FormUrlEncodedContent(parameters); 
  HttpResponseMessage response = await httpClient.PostAsync(url, content);

长连接和短连接适用场合:

1、需要实时获取数据时,这种情况只需建立一次连接后,不断,用长连接,不然频繁建立负荷较大,当然用Socket更好

2、只需要请求一次或几次数据,用短连接,比如:登录请求,如果使用长连接,连接资源持续被占用,也是浪费

代码测试

建立一个C#控制台应用程序

 Program.cs代码如下:

/*
 * 功能:Http Post 短连接请求
 * 作者:WangYadong
 * 日期:2024/11/14
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace HttpServerTest
{
    class Program
    {
        private static Timer timer;
        private static int timerLength=100; //计时器定位100ms,即0.1秒,该计时器每0.1秒就会执行一次
        static void Main(string[] args)
        {
            //关闭窗体程序时,注册退出事件
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);

            #region 实例化Http
            //开启Http请求(短连接)
            HttpPost httpPost = new HttpPost();
            //httpPost.InitHttpPost();

            //开启http请求(长连接)
            HttpPostLongConn httpPostLongConn = new HttpPostLongConn();
            httpPostLongConn.InitHttp();
            #endregion

            #region Timer计时器不断请求
            //申请计时器
            timer = new Timer(interval: timerLength);
            //timer.Elapsed += new ElapsedEventHandler(httpPostLongConn.HttpReqData);     //长连接,每0.1秒就会向服务器发送一次Post请求
            timer.Elapsed += new ElapsedEventHandler(httpPost.HttpPostData);             //短连接,每0.1秒就会向服务器发送一次Post请求
            timer.AutoReset = true;   //true,一直执行,false,执行一次
            timer.Enabled = true;
            timer.Start();
            #endregion

            Console.ReadLine();
        }

        /// <summary>
        /// 退出事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void OnProcessExit(object sender, EventArgs e)
        {
            //停止计时器
            if (timer != null)
            {
                timer.Enabled = false;
            }
        }
    }
}

Timer 是控制台程序中的一个计时器,本代码中定义的是100ms执行一次,即每0.1秒向服务器请求一次数据,亲测长连接和短连接都可请求成功

上述代码可以看出:

短连接每0.1秒向服务器发送请求的时候都要在 httpPost.HttpPostData() 函数里先建立了连接再请求数据

长连接我只在初始化的时候建立一次连接   httpPostLongConn.InitHttp(),然后每0.1秒向服务器请求数据的时候只在 httpPostLongConn.HttpReqData() 方法里传递参数即可

  • 结语

大家们应该注意到了本博主写的长连接是异步连接 ( await httpClient.PostAsync)。上面短连接本博主写的是微软官方给的传统连接,博主在此传统写法基础上将短连接改为长连接,上面被注释掉的 InitHttpPost() 方法就是,没成功,会报错,所以才不得已用的异步写法,报错信息如下:

有懂得大牛请赐教。。。。


http://www.kler.cn/a/411853.html

相关文章:

  • 在 PyTorch 训练中使用 `tqdm` 显示进度条
  • 【linux】(18)查看端口占用-netstat
  • 【数据分析】基于GEE解析2000-2020年武汉市FVC时空变化特征
  • Ubuntu下用Docker部署群晖系统---Virtual DSM --zerotier实现连接
  • Jmeter中的测试片段和非测试原件
  • 微信小程序学习指南从入门到精通
  • 【jvm】对象的内存布局
  • 【软件入门】Git快速入门
  • 《黑神话:悟空》游戏辅助修改器工具下载指南与操作方法详解
  • 4.6 JMeter HTTP信息头管理器
  • git(Linux)
  • C++:多态的原理
  • VMware ubuntu创建共享文件夹与Windows互传文件
  • Unity中的简易TCP服务器/客户端
  • macos 14.0 Monoma 修改顶部菜单栏颜色
  • Leetcode53. 最大子数组和(HOT100)
  • numpy.digitize函数介绍
  • 缺失的第一个正数(java)
  • 挂载本地目录到k8s的pod实现持久化存储
  • [java] 什么是 Apache Felix
  • wp the_posts_pagination 与分类页面搭配使用
  • git-显示顺序与提交顺序不一致的问题
  • unity3d——基础篇2刷(Mathf练习题)
  • RabbitMQ的预取值详解
  • 泷羽sec-linux进阶
  • postman的简单使用