C# HTTP 厌世请求法
HyperText Transfer Protocol (HTTP) 是一种基于 TCP 协议之上的应用层协议
HTTP 协议将会通过 TCP 传输层协议来传输特定的消息格式,HTTP 服务器将会正确理解 HTTP 客户端所发来的特定格式信息,并且 HTTP 服务器再返回一个特定格式信息给客户端
这是一个 HTTP 的请求消息格式
-
请求行: 包括 HTTP 方法, URL, HTTP 版本
-
请求头行: 包括多个请求头
-
内容
在 HTTP 1.1 中,Header 必须包括 Host
接下来为了表示厌世精神,我们将会在 C# 中放弃使用 HttpClient, WebClient, WebRequest, HttpWebRequest 等五花八门的方式,转而使用 Socket 类来发送 HTTP 请求
在 C# 中用 Socket 请求可比 C 方便多了 xDDDDD
请确保使用 System.Net.Sockets
这个命名空间,这样我们就能构造一个新的 Socket 了
1 | var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
AddressFamily.InterNetwork 我们将要使用 IPv4 的方式连接上我们的服务器
SocketType.Stream 数据将会以字节流的方式返回
ProtocolType 为 TCP,因为 HTTP 基于 TCP 协议
根据上面的图,我们需要手动编写 TCP 传输的消息
可以先看一个例子
请求行中包含方法,我们要请求的 URL 和一个 HTTP 版本
1 | GET /get |
这行结束之后我们需要一个空格符和一个回车符,使用用 \r
和 \n
下一行是请求头,HTTP 1.1 中要求至少包含 Host 请求头
1 | Host: httpbin.org |
一样的,当请求头结束之后也要加入空格符和回车符
如果你打算结束请求头行了,再次加入空格符和回车符
因此,我们的 TCP 消息结构会写成
1 | GET /get HTTP/1.1\r\nHost: httpbin.org\r\n\r\n |
写好之后,就可以开始准备发送请求了,为了演示,我将使用 httpbin.org 这个服务
通过
1 | socket.Connect("httpbin.org", 80) |
可以向 httpbin.org 的 80 端口通信
然后用
1 | socket.Send(Encoding.UTF8.GetBytes(httpMessage)); |
发出 TCP 连接
接着我们可以准备接收服务器回传的消息了
建立一个 response 的变量用于存放 HTTP 返回消息
因为目前还没有回传的消息,可以使用 string 里面的 Empty 字段来声明一个空的字符串类型数据
1 | var response = string.Empty; |
接下来建立 byte 并且把数据放进 byte 中
1 | var receivedBytes = new byte[socket.ReceiveBufferSize]; |
receivedBytes 的大小应该是 socket 接收到数据的 Buffer 的大小
然后用 socket.Receive 方法将数据放进 receivedBytes,并且拿到有多少 Bytes 在里面
最后通过一个循环把数据转成普通字符串,存进 response 变量中
1 | for (int i = 0; i < bytesRange; i++) |
最后就可以打印出来了
1 | Console.WriteLine(response); |
1 | HTTP/1.1 200 OK |
如果需要发送数据时,修改下消息结构就好了
当我们要发送 JSON 数据的时候,其实只需要加入 Content-Type 头为 application/json 并且最后携带上 JSON 格式的消息即可
回到我们的 HTTP 消息结构,先把 GET 改成 POST,并且别忘了把 URL 的 /get 改成 /post;因为 httpbin.org 接收 POST 请求的路由在 /post 下
加入 Content-Type 的头,内容为 application/json; charset=utf8
并且放入 Content-Length,目前为了演示,我们直接写死 38 就好
最后放入 JSON 数据
1 | {"message":"Ja! Ich bin eine Katze."} |
新的请求结构是这样的
1 | var httpMessage = |
再次启动就可以拿到新的数据了
1 | HTTP/1.1 200 OK |
Httpbin 的服务器已经正确的理解了本次请求并且将 JSON 解析放入 json 对象中
最后放上整个程序的 C# 代码
1 | var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |