在 .Net 中如何手动创建 HTTP 请求?

6
我想创建自己的自定义HTTP请求。WebClient类非常酷,但它会自动创建HTTP请求。我认为我需要创建一个网络连接到Web服务器并通过该流传输我的数据,但我不熟悉支持这种事情的库类。 (背景:我正在为我教授的Web编程课编写一些代码。我希望我的学生了解HTTP“黑盒”内部发生的基础知识。)
5个回答

21

要真正理解HTTP协议的内部机制,您可以使用TcpClient类:

using (var client = new TcpClient("www.google.com", 80))
{
    using (var stream = client.GetStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    {
        writer.AutoFlush = true;
        // Send request headers
        writer.WriteLine("GET / HTTP/1.1");
        writer.WriteLine("Host: www.google.com:80");
        writer.WriteLine("Connection: close");
        writer.WriteLine();
        writer.WriteLine();

        // Read the response from server
        Console.WriteLine(reader.ReadToEnd());
    }
}

另一种可能性是通过将以下内容放入您的app.config中来激活跟踪,然后只需使用WebClient执行HTTP请求:

<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.Net" tracemode="protocolonly">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Verbose"/>
    </switches>
    <sharedListeners>
      <add name="System.Net"
           type="System.Diagnostics.TextWriterTraceListener"
           initializeData="network.log" />
    </sharedListeners>
    <trace autoflush="true"/>
  </system.diagnostics>
</configuration>

然后您可以执行HTTP调用:

using (var client = new WebClient())
{
    var result = client.DownloadString("http://www.google.com");
}

最后,分析生成的network.log文件中的网络流量。 WebClient 还会跟随 HTTP 重定向。

很棒的例子,我期待着尝试它。这是一种很好的可视化方法,可以清晰地展示正在发生的事情。谢谢。 - Jeff

4
请使用所需的 WebRequestWebResponse 类。
如果您需要更低级别的操作,请查看其他 System.Net.Sockets.*Client 类,例如TcpClient

3

哎呀,到达网络请求的路途漫长而曲折。 - Joel Etherton
1
使用TcpClient还需要他理解Http所构建的TELNET协议。 - John Saunders
3
@John Saunders:HTTP不是建立在Telnet协议之上的。尽管可以使用Telnet客户端连接到Web服务器。 - Igor Korkhov
1
@Igor:我看你是对的。我一定把它和FTP搞混了。 - John Saunders

2
在我的回答中,我包括了创建HttpWebRequest和读取响应的基础知识。这是对SO帖子SharePoint 2007,如何检查文档库中是否存在文件夹的回应。
编辑:添加了来自上述帖子的代码示例。
System.Net.HttpWebRequest oReq; 
string sUrl = "http://yoursite/sites/somesite/DocumentLibrary"; 
oReq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(sUrl); 

oReq.Method = "GET"; 
oReq.Credentials = System.Net.CredentialCache.DefaultCredentials; 
oReq.AllowAutoRedirect = true; 

//now send the request
using (System.IO.StreamWriter oRequest = 
        new System.IO.StreamWriter(oReq.GetRequestStream())) { 
   oRequest.WriteLine(); 
}

//and read all the response
using (System.Net.HttpWebResponse oResponse = oReq.GetResponse()){
  using (System.IO.StreamReader oResponseReader = 
        new System.IO.StreamReader(oResponse.GetResponseStream())){
    string sResponse = oResponseReader.ReadToEnd(); 
  }
}

-1: StreamReader/Writer和响应中缺少using块。 - John Saunders
1
@John Saunders: 我知道“using”是编码的好模式,然而在StreamReader上调用close()确实会关闭底层流并“释放与读取器关联的任何系统资源”(请参阅MSDN文档)。所以如果你认为我在这里泄漏了什么东西,那么你是错的。 - naivists
不用担心。很久以前我就学会了示例代码总是带有“购买者自负”的标签。我宁愿有一个不完美的示例,也不愿意什么都没有。感谢你们的时间。+1 - Jeff
@John,听起来是真的。已经编辑了代码以根据需要进行Dispose(但我现在还没有测试它 :-))。 - naivists
@naivists:我已经取消了我的踩票。我唯一的其他顾虑是GetRequestStream/GetResponseStream调用,我会将它们分别放入不同的“using”块中,只是出于对读取器/写入器进行处理可能无法处理底层流的偏执。 - John Saunders
显示剩余2条评论

1

使用WFetch进行演示。

至于编程方面,HttpWebRequest可以让您控制请求的许多内容 - 如果是为了演示,我建议使用Wireshark来嗅探使用HttpWebRequest执行各种任务时传输的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接