【发布时间】:2017-05-04 20:04:39
【问题描述】:
我实际上是在尝试设置一个 HTTPS 客户端,可用于自动化测试 API 和我正在开发的其他 Web 服务。我熟悉使用套接字,但不太熟悉在代码中使用 SSL/TLS。我首先尝试设置一个客户端,该客户端使用以下标头向 google.com 发送 HTTP 请求:GET / HTTP/1.1
这个想法当然是通过加密连接从 Google 接收基本的 HTTP 响应。这在使用未加密的 HTTP 时非常简单——我什至可以通过端口 80 telnet 到 google 并输入 GET / HTTP/1.1,然后我会收到一个不错的 HTTP 响应标头和 HTML 有效负载。实现用于发出未加密 HTTP 请求的 C/C# 代码也不是很困难。是 SSL 给我带来了困难。
使用下面的代码(在https://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-3 找到的完整示例),它与MSDN 提供的参考实现几乎相同,我可以成功连接到google.com 并验证服务器证书:
// Create a TCP/IP client socket.
// machineName is the host running the server application.
TcpClient client = new TcpClient(machineName, 443);
Console.WriteLine("Client connected.");
// Create an SSL stream that will close the client's stream.
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
// The server name must match the name on the server certificate.
try
{
sslStream.AuthenticateAsClient(serverName);
}
catch (AuthenticationException e)
{
Console.WriteLine("Exception: {0}", e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
return;
}
问题是当执行以下代码时,ReadMessage(sslStream) 指令挂起,因为我很长时间没有收到响应,并且当响应最终到达时,它是一个空字符串:
// Encode a test message into a byte array.
// Signal the end of the message using the "<EOF>".
byte[] messsage = Encoding.UTF8.GetBytes("GET / HTTP/1.1<EOF>");
// Send hello message to the server.
sslStream.Write(messsage);
sslStream.Flush();
// Read message from the server.
string serverMessage = ReadMessage(sslStream);
Console.WriteLine("Server says: {0}", serverMessage);
因此,当我通过安全套接字连接发出此请求时,我无法接收到我正在寻找的 HTTP 响应(或任何东西)。从长远来看,这个想法是开始使用这个客户端向我自己的 API 和 Web 服务发送定制的 HTTP 请求,但如果我什至无法从 google.com 获得通用响应,我当然不能这样做。有谁知道为什么 ReadMessage() 函数超时或不提供响应?示例代码看起来非常简单,所以我很难理解我做错了什么。
【问题讨论】:
-
"
" 会破坏 HTTP 请求,使其无法被 Web 服务器解析,这是什么? GET 应该以 \r\n 结束 -
是由来自 MSDN 的参考代码中的 cmets 建议的。我会尝试用 \r\n 替换它,但我遇到了同样的行为。 -
我知道这是一篇旧帖子,但我认为正确的终止符是 "\r\n\r\n" 而不仅仅是 \r\n。
-
@anthonyterra 你是对的 - 原因是第一个 \r\n 只会让你到达将表单数据添加到 HTTP 标头的位置。添加另一个 \r\n 信号表明表单数据已提供或不包含在内。
标签: c# asp.net sockets ssl https