为什么在 C# 中使用 HttpClient 时会出现"The response ended prematurely"?



我在。net Core中的第一个HTTP客户端代码。服务器也在我的PC上运行,所以我想把它发送到localhost。

在有人推荐之后,我添加了内部异常的打印,但这还不足以让我理解问题。

namespace HTTPClient
{
// The object I want to send
public class Msg
{
public string ID { get; set; }
public string Data { get; set; }
public int RSSIR { get; set; }
public int RSSIT { get; set; }
public int Slot { get; set; }
}
class Program
{
static Msg msg = new Msg
{
ID = "00CC",
Data = "9F4CC",
RSSIR = 123, 
RSSIT = 321,
Slot = 1
};
static void Main(string[] args)
{
string url = "http://127.0.0.1:5001";
Console.WriteLine("result = " , callURL(url)); 
Console.ReadKey();
}

public static bool callURL(string url)
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
bool Result = false;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = null;
try
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent content = new StringContent(JsonConvert.SerializeObject(msg), Encoding.UTF8, "application/json");
response = client.PostAsync("", content).Result;
}
catch (AggregateException err)
{
foreach (var errInner in err.InnerExceptions)
{   // for printing the inner execption
Console.WriteLine("ERROR");
Console.WriteLine(errInner); 
}
}

if (response.IsSuccessStatusCode)
{
Result = true;
}
else
{
Result = false;
}
return Result;
}

}
}

我从catch内的循环收到的错误是:

System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The response ended prematurely.
at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)

我怎样才能弄清楚为什么我不能向服务器发送消息?消息的内容是否会中断连接的生成?

我用另一个客户端检查了服务器,它正在工作,所以问题必须在我的代码中。

编辑:服务器正在使用https,所以我将URL更改为https,这是我收到的错误:

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)

我需要添加一些SSL命令来建立安全连接吗?

Edit2:在callURL()

中添加命令后的新错误
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)

System.IO.IOException: The response ended prematurely表示您正在发送HTTP请求的服务器在没有发送完整响应的情况下关闭了连接。

,什么与你的客户代码,编译,看起来正确发送内容

是的,你应该使用await client.PostAsync,但是与你的问题完全无关

仔细检查http://127.0.0.1:5001是100%正确的-也许它是https://或不是端口5001


如果它是一个使用HTTPS的端点,你可能会得到System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.,因为它看起来像你正在调用本地端点。

。. NET默认执行SSL证书验证&如果您试图调用没有/无效SSL证书的HTTPS端点,将抛出异常。您可能没有在您的机器上正确设置本地主机证书。

现在,您可以通过使用HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

ServicePointManager.ServerCertificateValidationCallback设置为始终返回true

来绕过检查。像下面这样初始化你的HttpClient:

public static bool callURL(string url)
{
bool Result = false;
var httpClientHandler = new HttpClientHandler();

#if DEBUG
httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
#endif
HttpClient client = new HttpClient(httpClientHandler);
...
}

但是,请注意允许所有SSL证书如果在本地开发环境以外的任何地方使用,则存在安全风险。.

阅读:世界上最危险的代码:验证非浏览器软件中的SSL证书斯坦福大学

我在将。net框架项目移植到。net core时遇到了类似的问题。我设法解决它通过使用WinHttpHandler像这样:

var handler = new WinHttpHandler();
handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
handler.TcpKeepAliveEnabled = true;
using (var hc = new HttpClient(handler))
{
return wc.GetStringAsync(new Uri(apiUrl)).GetAwaiter().GetResult();
}

如果这些解决方案不适合您,请尝试以下方法。在某些特殊情况下,可能会触发函数,但不会触发编排器,也可能会抛出异常,说"本地机器主动拒绝连接到端口7071"。这样做的主要原因是你的TaskHub持久函数在本地存储模拟器中创建了一个本地TaskHub来运行这些函数。它完全依赖于您的本地机器,如果它以某种方式损坏。它可能会导致上述各种问题。大多数情况下,通过清除LocalStorageEmulator并创建一个新的TaskHub,重新启动整个机器就可以解决问题。如果这并不工作然后在VS代码下载一个扩展名为"Monitor"耐用功能。

扩展Id:DurableFunctionsMonitor.durablefunctionsmonitor名称:持久函数监视器Id: DurableFunctionsMonitor.durablefunctionsmonitor描述:Azure持久函数的监控/调试UI工具版本:6.2.0出版者:DurableFunctionsMonitorVS市场链接:https://marketplace.visualstudio.com/items?itemName=DurableFunctionsMonitor.durablefunctionsmonitor

,一旦安装在LocalStorageEmulator下,就会有一些任务中心,删除所有的任务中心,重新启动你的Visual Studio,这将解决你的问题。

相关内容

  • 没有找到相关文章

最新更新