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秒(或者更频繁)向服务器请求数据,以保证数据实时在界面上更新显示。那这种情况短连接就不适用了,因为短连接每次都需要建立新连接,然后向服务器发送请求,拿到数据后再断开,下次再重复此操作。这样比较费资源,简单的数据请求可以支持,但如果数据量繁重的情况下怎么办呢?这会给电脑造成很重的负担,这时就需要长连接进行请求了。
长连接请求:
所谓长连接就是只建立一次连接后,不断开,下次进行数据请求时直接发送参数即可
长连接与短接的区别就在于在请求头中设置
Connection
为keep-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() 方法就是,没成功,会报错,所以才不得已用的异步写法,报错信息如下:
有懂得大牛请赐教。。。。