#c# #http #.net-core #httpclient
Вопрос:
Мой первый код HTTP-клиента в .Net Core. Сервер также работает на моем компьютере, поэтому я хочу отправить его на локальный хост.
Я добавил печать внутреннего исключения после того, как кто-то рекомендовал его здесь, но этого недостаточно, чтобы я понял проблему.
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).Resu<
}
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 Resu<
}
}
}
Ошибка, которую я получил из цикла внутри ловушки, состоит в том, что:
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)
Комментарии:
1. Сделайте
catch (Exception err)
, а затемConsole.WriteLine(err.ToString());
— каковы полные сведения об исключении?2.
HttpClient
использует асинхронный ввод — поэтому вы должны использоватьasync
методы сawait
. Вы не должны использовать.Result
, потому что это может привести к взаимоблокировкам.3. @ErmiyaEskandary Значение ошибки: msg: Произошла одна или несколько ошибок. (При отправке запроса произошла ошибка.) источник: Система. Частное. Трассировка ядра: в системе. Нарезание резьбы. Задачи.Задачи. ThrowIfExceptional(логические исключения includeTaskCanceledExceptions) в системе. Нарезание резьбы. Задачи. Задача
1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task
1.get_Result() в HttpClient. Program.callURL(URL-адрес строки) в C:sourceHTTPClientHTTPClientProgram.cs:line 844. Правильно ли 127.0.0.1:5001 на 100%? Работает ли сервер? Ваш код работает так, что бы это ни было, это серверная сторона
5. @ErmiyaEskandary Я только что увидел, что сервер использует https, и я использовал HTTP, поэтому я изменил HTTP на https, и я получил новую ошибку (В сообщении)
Ответ №1:
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-сертификата и создаст исключение, если вы пытаетесь вызвать конечную точку HTTPS, для которой у вас нет/недействительного SSL-сертификата. Возможно, вы неправильно настроили сертификат localhost на своем компьютере.
На данный момент вы можете обойти проверку, установив параметр ServicePointManager.ServerCertificateValidationCallback
всегда возвращаться true
с помощью HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
Инициализируйте ваше 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-сертификатов в не-браузерном программном обеспечении Стэнфордского университета
Комментарии:
1. Теперь это работает. Очень странно.. Большое спасибо!
2. @RoyAncri Не пропускайте проверку сертификации в производстве, однако для разработки это будет нормально. Установка правильного SSL — сертификата на производственном сервере позволит вам удалить приведенный выше код, который представляет угрозу безопасности, если оставить его в таком виде на чем-либо, кроме сборок разработчиков-надеюсь, это поможет!
3. @ErmiyaEskandary Да, я прочитаю, как это сделать для производственного проекта. Еще раз спасибо