HTTP请求需要引入的命名空间
using System.Net;
1、先整个窗体
我会先些一个命令行程序分别实现GET请求和POST请求,这是最终的窗体程序。
如下:
- url输入框用来获取要发起的http请求的地址
- GET/POST 单选框用来选择发起的http请求的方式
- 选择post方式的时候,需要在输入文本框输入内容
- 点击连接按钮发起请求
- 发起请求后获得的响应会显示到响应文本框
2、设置一下服务器
用nodejs实现的服务器逻辑,用PHP更方便。
var _http = require('http');
var _query = require('querystring');
var server = _http.createServer(function (req, res) {
res.writeHead(200, {"Content-Type": 'text/html;charset=utf-8'});
let obj;
//如果请求方式是POST
if(req.method == "POST"){
var buff = '';
//监控响应内容
req.on('data', (data) => {
buff += data;
});
req.on('end', () => {
obj = _query.parse(buff);
var a = 'POST 方式的请求,请求内容:'+JSON.stringify(obj);
//把 a 作为响应的数据返回给请求方。
res.end(a);
});
}
if(req.method == "GET"){
//把url里的query字符串(a=abc&b=bbb)解析成对象obj
obj = _query.parse(req.url);
var a = 'GET 方式的请求,请求内容:'+JSON.stringify(obj);
//把 a作为响应的数据返回给请求方。
res.end(a);
}
//把 a 显示到命令行
console.log(a);
});
//服务器端口设置为3001
server.listen(3001, function () {
console.log('服务器创建成功!port:3001');
});
3、实现http GET请求
//请求的http地址
string url = "http://localhost:3001/qq?a=abc&b=bbb";
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
StreamReader reader = null;
string content = string.Empty;
try
{
//实例化一个http请求
request = (HttpWebRequest)WebRequest.Create(url);
//设置请求头 请求方式method=get
request.Method = "GET";
//使request。getResponse()返回的一个响应对象
response = (HttpWebResponse)request.GetResponse();
//reader 读取响应流
using (reader = new StreamReader(response.GetResponseStream()))
{
//意思是从头读到尾,全部读完
content = reader.ReadToEnd();
}
}
catch (System.Exception err)
{
Console.WriteLine("1.GET出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
Console.WriteLine("响应:" + content);
//为啥read大家都懂
Console.Read();
看一下效果:
输出符合预期,显然代码是可行。
4、接下来实现的是post请求
//请求的http地址
string url = "http://localhost:3001/qq?a=abc&b=bbb";
//要发送的数据
string msg = "method is post.";
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
//post请求需要一个流把数据写进去
Stream requestStream = null;
StreamReader reader = null;
//request所携带的数据是字节码,所以msg需要转化为byte[]数组才能读入
var data = Encoding.UTF8.GetBytes(string.Format("a={0}&b={1}", "message", msg));
string content = string.Empty;
try
{
//实例化一个http请求
request = (HttpWebRequest)WebRequest.Create(url);
//设置请求头 请求方式method=post
request.Method = "POST";
//请求类型
request.ContentType = "application/text";
requestStream = request.GetRequestStream();
requestStream.Write(data, 0, data.Length);
response = (HttpWebResponse)request.GetResponse();
//reader 读取响应流
using (reader = new StreamReader(response.GetResponseStream()))
{
content = reader.ReadToEnd();
}
}
catch (System.Exception err)
{
Console.WriteLine("1.POST出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
Console.WriteLine("响应:" + content);
Console.Read();
输出:
5、封装成函数
封装的函数已经可以直接使用了。
首先是GET请求:
/// <summary>
/// GET方式发送得结果
/// </summary>
/// <param name="url">请求的url</param>
/// <returns>服务器响应的数据</returns>
public static string getHttpRequest(string url)
{
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
StreamReader reader = null;
string content = string.Empty;
try
{
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
response = (HttpWebResponse)request.GetResponse();
using (reader = new StreamReader(response.GetResponseStream()))
{
content = reader.ReadToEnd();
}
}
catch (System.Exception err)
{
MessageBox.Show("1.GET出现了错误!\n错误来源:" + err.Source + "\n错误信息:" + err.Message+"\n"+err);
Console.WriteLine("1.GET出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
//用完销毁
response.Dispose();
reader.Dispose();
return content;
}
然后是POST方式:
/// <summary>
/// 发起一个http请求,方式为POST
/// </summary>
/// <param name="uri">发送请求的目标url</param>
/// <param name="reMsg">要发送的消息</param>
/// <returns>服务器响应的数据</returns>
public string postHttpRequest(string uri, string msg)
{
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
Stream requestStream = null;
StreamReader reader = null;
var data = Encoding.UTF8.GetBytes(string.Format("a={0}&b={1}", "message", msg));
string content = "";
try
{
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
requestStream = request.GetRequestStream();
request.ContentType = "application/text";
requestStream.Write(data, 0, data.Length);
response = (HttpWebResponse)request.GetResponse();
using (reader = new StreamReader(response.GetResponseStream()))
{
content = reader.ReadToEnd();
}
}
catch (Exception err) {
MessageBox.Show("1.POST出现了错误!\n错误来源:" + err.Source + "\n错误信息:" + err.Message + "\n" + err);
Console.WriteLine("1.POST出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
//资源用完回收
requestStream.Dispose();
response.Dispose();
reader.Dispose();
return content;
}
注意事项
这里需要注意的是,封装后我加了几段销毁资源的代码。这个http请求方法我原本是用来进行一个课设项目的:本地程序 APP 监控一个温度感应器,每500毫秒就通过串口获取感应器的温度信息,然后通过http轮询把温度数据发送给服务器。
但是在给老师演示的时候,演示的时间长了点,这个APP的后台内存占用五分钟飙升了600MB。
后来看了一下微软的C#文档,原因是C#的垃圾回收机制 C#的垃圾回收机制 | 微软文档 ,用人能看懂的话描述就是:C#的垃圾回收器会不断遍历内存,查看哪些内存不再使用的,就打上标记,每隔一段时间回收一次被标记的内存。
但是在我发起的http请求中,我使用了reader读取响应流,却没有关闭它。让垃圾回收器以为这些资源还在使用,所以没有被回收造成了内存堆积。于是如果使用上面的方法进行http轮询,就需要手动回收内存。
6、在窗体程序中演示
GET方式:
POST方式:
下面是窗体程序的完整代码:
using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
namespace CSharp_http
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnConnec_Click(object sender, EventArgs e)
{
if (rabPOST.Checked && (txtSend.Text == "" || txtSend.Text == null))
{
MessageBox.Show("POST方式进行请求请输入信息");
txtSend.Focus();
}
else {
if (rabGET.Checked)
{
//如果是get请求方式
txtRecive.Text = getHttpRequest(txtURL.Text.Trim());
}
else {
//如果是post请求方式
txtRecive.Text = postHttpRequest(txtURL.Text.Trim(),txtSend.Text);
}
}
}
/// <summary>
/// GET方式发送得结果
/// </summary>
/// <param name="url">请求的url</param>
/// <returns>服务器响应的数据</returns>
public static string getHttpRequest(string url)
{
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
StreamReader reader = null;
string content = string.Empty;
try
{
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
//hwRequest.Timeout = 30000;
//hwRequest.ContentType = "application/text";
response = (HttpWebResponse)request.GetResponse();
using (reader = new StreamReader(response.GetResponseStream()))
{
content = reader.ReadToEnd();
}
}
catch (System.Exception err)
{
MessageBox.Show("1.GET出现了错误!\n错误来源:" + err.Source + "\n错误信息:" + err.Message+"\n"+err);
Console.WriteLine("1.GET出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
//用完销毁
response.Dispose();
reader.Dispose();
return content;
}
/// <summary>
/// 发起一个http请求,方式为POST
/// </summary>
/// <param name="uri">发送请求的目标url</param>
/// <param name="reMsg">要发送的消息</param>
/// <returns>服务器响应的数据</returns>
public string postHttpRequest(string uri, string msg)
{
//预备请求的资源
HttpWebRequest request = null;
HttpWebResponse response = null;
Stream requestStream = null;
StreamReader reader = null;
var data = Encoding.UTF8.GetBytes(string.Format("a={0}&b={1}", "message", msg));
string content = "";
try
{
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
requestStream = request.GetRequestStream();
request.ContentType = "application/text";
requestStream.Write(data, 0, data.Length);
response = (HttpWebResponse)request.GetResponse();
using (reader = new StreamReader(response.GetResponseStream()))
{
content = reader.ReadToEnd();
}
}
catch (Exception err) {
MessageBox.Show("1.POST出现了错误!\n错误来源:" + err.Source + "\n错误信息:" + err.Message + "\n" + err);
Console.WriteLine("1.POST出现了错误!\n错误来源:" + err.Source + "错误信息:" + err.Message);
}
//资源用完回收
requestStream.Dispose();
response.Dispose();
reader.Dispose();
return content;
}
}
}
PS:整个窗体小程序的解决方案我打包上传了,有兴趣的可以下载来康康