GetRequestStream() исключает тайм-аут при отправке данных на HTTPS-url
Я вызываю API, размещенный на сервере Apache, для публикации данных. Я использую HttpWebRequest для выполнения POST в С#.
API имеет как обычный HTTP, так и защищенный уровень (HTTPS) PORT на сервере. Когда я вызываю URL-адрес HTTP, он работает отлично. Однако, когда я вызываю HTTPS, он дает мне исключение тайм-аута (в функции GetRequestStream()). Какие-нибудь идеи? Я использую VS 2010,.Net framework 3.5 и С#. Вот кодовый блок:
string json_value = jsonSerializer.Serialize(data);
HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create("https://server-url-xxxx.com");
request.Method = "POST";
request.ProtocolVersion = System.Net.HttpVersion.Version10;
request.ContentType = "application/x-www-form-urlencoded";
byte[] buffer = Encoding.ASCII.GetBytes(json_value);
request.ContentLength = buffer.Length;
System.IO.Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
EDIT:
Консольная программа, предложенная Питером, отлично работает. Но когда я добавляю данные (в формате JSON), которые должны быть отправлены в API, это исключает исключение из строя. Вот код, который я добавляю к консольному приложению, и он выдает ошибку.
byte[] buffer = Encoding.ASCII.GetBytes(json_value);
request.ContentLength = buffer.Length;
Ответы
Ответ 1
Я не знаю, поможет ли это вам в вашей конкретной проблеме, но вам следует рассмотреть возможность удаления некоторых из этих объектов, когда вы закончите с ними. В последнее время я делал что-то вроде этого, и обертывание файлов с помощью операторов, похоже, очищает кучу исключений таймаута для меня.
using (var reqStream = request.GetRequestStream())
{
if (reqStream == null)
{
return;
}
//do whatever
}
также проверьте эти вещи
- Сервер, обслуживающий https в локальной локальной среде?
- Правильно ли вы настроили привязки *.443 (https)?
- Вам нужно установить учетные данные в запросе?
- Будет ли ваша учетная запись пула приложений доступ к ресурсам https или будет ли ваша учетная запись передана через?
-
Задумывались ли вы об использовании WebClient?
using (WebClient client = new WebClient())
{
using (Stream stream = client.OpenRead("https://server-url-xxxx.com"))
using (StreamReader reader = new StreamReader(stream))
{
MessageBox.Show(reader.ReadToEnd());
}
}
EDIT:
сделать запрос с консоли.
internal class Program
{
private static void Main(string[] args)
{
new Program().Run();
Console.ReadLine();
}
public void Run()
{
var request = (HttpWebRequest)System.Net.WebRequest.Create("https://server-url-xxxx.com");
request.Method = "POST";
request.ProtocolVersion = System.Net.HttpVersion.Version10;
request.ContentType = "application/x-www-form-urlencoded";
using (var reqStream = request.GetRequestStream())
{
using(var response = new StreamReader(reqStream )
{
Console.WriteLine(response.ReadToEnd());
}
}
}
}
Ответ 2
Я столкнулся с той же проблемой. Кажется, он решен для меня. Я прошел весь свой код, убедившись, что для всех объектов HttpWebResponse вызывается webResponse.Close() и/или responseStream.Close(). Документация указывает, что вы можете закрыть поток или объект HttpWebResponse. Вызов обоих не вреден, поэтому я и сделал. Не закрывая ответы может привести к тому, что приложение перестанет подключаться для повторного использования, и это, похоже, влияет на HttpWebRequest.GetRequestStream, насколько я могу заметить в своем коде.
Ответ 3
Попробуйте следующее:
WebRequest req = WebRequest.Create("https://server-url-xxxx.com");
req.Method = "POST";
string json_value = jsonSerializer.Serialize(data); //Body data
ServicePointManager.Expect100Continue = false;
using (var streamWriter = new StreamWriter(req.GetRequestStream()))
{
streamWriter.Write(json_value);
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
Stream GETResponseStream = resp.GetResponseStream();
StreamReader sr = new StreamReader(GETResponseStream);
var response = sr.ReadToEnd(); //Response
resp.Close(); //Close response
sr.Close(); //Close StreamReader
И просмотрите URI:
-
Зарезервированные символы. Отправить зарезервированные символы по URI может принести проблемы ! * ' ( ) ; : @ & = + $ , / ? # [ ]
-
Длина URI: вы не должны превышать 2000 символов
Ответ 4
Возможно, вы захотите установить свойство timeout, проверьте его здесь http://www.codeproject.com/Tips/69637/Setting-timeout-property-for-System-Net-WebClient
Ответ 5
Я тоже столкнулся с этим. Я хотел симулировать сотни пользователей с помощью консольного приложения. При моделировании только одного пользователя все было хорошо. Но с увеличением числа пользователей все время возникает исключение Timeout.
Тайм-аут происходит, потому что по умолчанию ConnectionLimit = 2 для ServicePoint (он же веб-сайт).
Очень хорошая статья для чтения: https://venkateshnarayanan.wordpress.com/2013/04/17/httpwebrequest-reuse-of-tcp-connections/
Что вы можете сделать, это:
1) создать больше ConnectionGroups в пределах servicePoint, потому что ConnectionLimit для каждой ConnectionGroups.
2) или вы просто увеличиваете лимит подключения.
Смотрите мое решение:
private HttpWebRequest CreateHttpWebRequest<U>(string userSessionID, string method, string fullUrl, U uploadData)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(fullUrl);
req.Method = method; // GET PUT POST DELETE
req.ConnectionGroupName = userSessionID; // We make separate connection-groups for each user session. Within a group connections can be reused.
req.ServicePoint.ConnectionLimit = 10; // The default value of 2 within a ConnectionGroup caused me always a "Timeout exception" because a user 1-3 concurrent WebRequests within a second.
req.ServicePoint.MaxIdleTime = 5 * 1000; // (5 sec) default was 100000 (100 sec). Max idle time for a connection within a ConnectionGroup for reuse before closing
Log("Statistics: The sum of connections of all connectiongroups within the ServicePoint: " + req.ServicePoint.CurrentConnections; // just for statistics
if (uploadData != null)
{
req.ContentType = "application/json";
SerializeToJson(uploadData, req.GetRequestStream());
}
return req;
}
/// <summary>Serializes and writes obj to the requestStream and closes the stream. Uses JSON serialization from System.Runtime.Serialization.</summary>
public void SerializeToJson(object obj, Stream requestStream)
{
DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());
json.WriteObject(requestStream, obj);
requestStream.Close();
}