超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信。
HTTP 的工作方式是客户端与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。
在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。
关于GET和POST的一些区别
GET | POST |
---|---|
Get 是用来从服务器上获得数据 | Post 是用来向服务器上传递数据 |
Get 将表单中数据的按照 variable=value 的形式,添加到 action 所指向的 URL 后面,并且两者使用“?”连接,而各个变量之间使用“&”连接 | Post 是将表单中的数据放在 form 的数据体中,按照变量和值相对应的方式,传递到 action 所指向 URL。 |
Get 是不安全的,因为在传输过程,数据被放在请求的 URL 中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前 | Post 的所有操作对用户来说都是不可见的 |
Get 传输的数据量小,这主要是因为受 URL 长度限制 | Post 可以传输大量的数据,所以在上传文件只能使用 Post |
Get 限制 Form 表单的数据集的值必须为 ASCII 字符 | Post 支持整个 ISO10646 字符集。 |
Get 是 Form 的默认方法 |
使用 Post 传输的数据,可以通过设置编码的方式正确转化中文;而 Get 传输的数据却没有变化。在以后的程序中,我们一定要注意这一点。
其他 HTTP 请求方法
方法 | 描述 |
---|---|
HEAD | 与 GET 相同,但只返回 HTTP 报头,不返回文档主体 |
PUT | 上传指定的 URI 表示 |
DELETE | 删除指定资源 |
OPTIONS | 返回服务器支持的 HTTP 方法 |
CONNECT | 把请求连接转换到透明的 TCP/IP 通道 |
如果想尝试在线使用这些HTTP方法,可以使用这个网站进行验证:http://www.ouapi.com/
最后,仿照这个网站,做出了一个界面。
代码可以看我的Github地址:https://github.com/AnTi-anti/PostAndGet
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的,是向服务器来传递数据。
POST /test/demo_form.php HTTP/1.1
Host: cdsy.xyz
name1=value1&name2=value2
有关 POST 请求的其他一些注释:
using System.Net.Http;
using System.Net;
Encoding myEncoding = Encoding.GetEncoding("gb2312"); //选择编码字符集
string data = "sn=" + _uScanCode + "&lanMac=" + _sRecieveLanMac + "&wifiMac=" + _sRecieveWifi2Mac + "&testUserName=" + sTestUser + "&testDateTime=" + sTimeStr; //要上传到网页系统里的数据(字段名=数值 ,用&符号连接起来)
byte[] bytesToPost = System.Text.Encoding.Default.GetBytes(data); //转换为bytes数据
string responseResult = String.Empty;
HttpWebRequest req = (HttpWebRequest)
HttpWebRequest.Create("http://192.168.60.59:81/rpc/snBurn/insertBySN"); //创建一个有效的httprequest请求,地址和端口和指定路径必须要和网页系统工程师确认正确,不然一直通讯不成功
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded;charset=gb2312";
req.ContentLength = bytesToPost.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(bytesToPost, 0, bytesToPost.Length); //把要上传网页系统的数据通过post发送
}
HttpWebResponse cnblogsRespone = (HttpWebResponse)req.GetResponse();
if (cnblogsRespone != null && cnblogsRespone.StatusCode == HttpStatusCode.OK)
{
StreamReader sr;
using (sr = new StreamReader(cnblogsRespone.GetResponseStream()))
{
responseResult = sr.ReadToEnd(); //网页系统的json格式的返回值,在responseResult里,具体内容就是网页系统负责工程师跟你协议号的返回值协议内容
}
sr.Close();
}
cnblogsRespone.Close();
请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的,是从服务器上来获取数据。
/test/demo_form.php?name1=value1&name2=value2
有关 GET 请求的其他一些注释:
/// <summary>
/// 指定Url地址使用Get 方式获取全部字符串
/// </summary>
/// <param name="url">请求链接地址</param>
/// <returns></returns>
public static string Get(string url)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
try
{
//获取内容
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
}
finally
{
stream.Close();
}
return result;
}
/// <summary>
/// 发送Get请求
/// </summary>
/// <param name="url">地址</param>
/// <param name="dic">请求参数定义</param>
/// <returns></returns>
public static string Get(string url, Dictionary<string, string> dic)
{
string result = "";
StringBuilder builder = new StringBuilder();
builder.Append(url);
if (dic.Count > 0)
{
builder.Append("?");
int i = 0;
foreach (var item in dic)
{
if (i > 0)
builder.Append("&");
builder.AppendFormat("{0}={1}", item.Key, item.Value);
i++;
}
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(builder.ToString());
//添加参数
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
try
{
//获取内容
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
}
finally
{
stream.Close();
}
return result;
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
req.Headers["Accept-Language"] = "zh-CN,zh;q=0.8";
req.Referer = "https://www.baidu.com/";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
string result = "";
//注意,此处使用的编码是:gb2312
//using (StreamReader reader = new StreamReader(stream, Encoding.Default))
using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("gb2312")))
{
result = reader.ReadToEnd();
}
PUT 用于将数据发送到服务器来创建/更新资源。
POST 和 PUT之间的区别在于 PUT 请求是幂等的(idempotent)。也就是说,多次调用相同的 PUT 请求将始终产生相同的结果。相反,重复调用POST请求具有多次创建相同资源的副作用。
/// <summary>
/// 通用请求方法
/// </summary>
/// <param name="url"></param>
/// <param name="datas"></param>
/// <param name="method">POST GET PUT DELETE</param>
/// <param name="contentType">"POST application/x-www-form-urlencoded; charset=UTF-8"</param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string HttpRequest(string url, string data, string method = "PUT", string contentType = "application/json", Encoding encoding = null)
{
byte[] datas = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(data);//data可以直接传字节类型 byte[] data,然后这一段就可以去掉
if (encoding == null)
encoding = Encoding.UTF8;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = method;
request.Timeout = 150000;
request.AllowAutoRedirect = false;
if (!string.IsNullOrEmpty(contentType))
{
request.ContentType = contentType;
}
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
}
Stream requestStream = null;
string responseStr = null;
try
{
if (datas != null)
{
request.ContentLength = datas.Length;
requestStream = request.GetRequestStream();
requestStream.Write(datas, 0, datas.Length);
requestStream.Close();
}
else
{
request.ContentLength = 0;
}
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
{
Stream getStream = webResponse.GetResponseStream();
byte[] outBytes = ReadFully(getStream);
getStream.Close();
responseStr = Encoding.UTF8.GetString(outBytes);
}
}
catch (Exception)
{
throw;
}
finally
{
request = null;
requestStream = null;
}
return responseStr;
}
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true; //总是接受
}
public static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[512];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
HEAD 与 GET 几乎相同,但没有响应主体。
换句话说,如果 GET /users 返回用户列表,那么 HEAD /users 将发出相同的请求,但不会返回用户列表。
HEAD 请求对于在实际发出 GET 请求之前(例如在下载大文件或响应正文之前)检查 GET 请求将返回的内容很有用。
static async void HttpClientSendAsync()
{
var client = new HttpClient(new HttpClientHandler { UseProxy = false });
var request = new HttpRequestMessage(HttpMethod.Post, "http://www.albahari.com/EchoPost.aspx");
request.Content = new StringContent("This is a test!");
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
DELETE 方法删除指定的资源
OPTIONS 方法描述目标资源的通信选项
using Newtonsoft.Json;
static public string ConvertJsonString(string json)
{
JsonSerializer serializer = new JsonSerializer();
TextReader tr = new StringReader(json);
JsonTextReader jtr = new JsonTextReader(tr);
object obj = serializer.Deserialize(jtr);
if (obj != null)
{
StringWriter textWriter = new StringWriter();
JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
{
Formatting = Formatting.Indented,
Indentation = 4,
IndentChar = ' '
};
serializer.Serialize(jsonWriter, obj);
return textWriter.ToString();
}
else
{
return json;
}
}