C# 将数据发布到 HTTPS url 时,GetRequestStream() 抛出超时异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9627669/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GetRequestStream() is throwing time out exception when posting data to HTTPS url
提问by Wiz
I'm calling an API hosted on Apache server to post data. I'm using HttpWebRequest to perform POST in C#.
我正在调用托管在 Apache 服务器上的 API 来发布数据。我正在使用 HttpWebRequest 在 C# 中执行 POST。
API has both normal HTTP and secure layer (HTTPS) PORT on the server. When I call HTTP URL it works perfectly fine. However, when I call HTTPS it gives me time-out exception (at GetRequestStream() function). Any insights? I'm using VS 2010, .Net framework 3.5 and C#. Here is the code block:
API 在服务器上同时具有正常的 HTTP 和安全层 (HTTPS) 端口。当我调用 HTTP URL 时,它工作得很好。但是,当我调用 HTTPS 时,它给了我超时异常(在 GetRequestStream() 函数处)。任何见解?我正在使用 VS 2010、.Net 框架 3.5 和 C#。这是代码块:
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: The console program suggested by Peter works fine. But when I add data (in JSON format) that needs to be posted to the API, it throws out operation timed out exception. Here is the code that I add to console based application and it throws error.
编辑:彼得建议的控制台程序工作正常。但是当我添加需要发布到 API 的数据(以 JSON 格式)时,它会抛出操作超时异常。这是我添加到基于控制台的应用程序的代码,它引发错误。
byte[] buffer = Encoding.ASCII.GetBytes(json_value);
request.ContentLength = buffer.Length;
采纳答案by Peter
I don't know if this will help you with your specific problem but you should consider Disposing some of those objects when you are finished with them. I was doing something like this recently and wrapping stuff up in using statements seems to clean up a bunch of timeout exceptions for me.
我不知道这是否会帮助您解决您的特定问题,但是您应该考虑在完成这些对象后处理它们。我最近在做这样的事情,在 using 语句中包装东西似乎为我清理了一堆超时异常。
using (var reqStream = request.GetRequestStream())
{
if (reqStream == null)
{
return;
}
//do whatever
}
also check these things
还要检查这些东西
- Is the server serving https in your local dev environment?
- Have you set up your bindings *.443 (https) properly?
- Do you need to set credentials on the request?
- Is it your application pool account accessing the https resources or is it your account being passed through?
Have you thought about using WebClient instead?
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()); } }
- 服务器是否在您的本地开发环境中提供 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:
编辑:
make a request from console.
从控制台发出请求。
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());
}
}
}
}
回答by seUser
You may want to set timeout property, check it here http://www.codeproject.com/Tips/69637/Setting-timeout-property-for-System-Net-WebClient
您可能想要设置超时属性,请在此处查看http://www.codeproject.com/Tips/69637/Setting-timeout-property-for-System-Net-WebClient
回答by DDRider62
I ran into the same issue. It seems like it is solved for me. I went through all my code making sure to invoke webResponse.Close()and/or responseStream.Close()for all my HttpWebResponse objects. The documentation indicates that you can close the stream or the HttpWebResponse object. Calling both is not harmful, so I did. Not closing the responses may cause the application to run out of connections for reuse, and this seems to affect the HttpWebRequest.GetRequestStream as far as I can observe in my code.
我遇到了同样的问题。似乎对我来说已经解决了。我检查了所有代码,确保为所有 HttpWebResponse 对象调用webResponse.Close()和/或responseStream.Close()。该文档表明您可以关闭流或 HttpWebResponse 对象。调用两者都无害,所以我做了。不关闭响应可能会导致应用程序耗尽连接以供重用,并且就我在代码中观察到的而言,这似乎会影响 HttpWebRequest.GetRequestStream。
回答by J.C. Gras
Try this:
尝试这个:
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
And review the URI:
并查看 URI:
Reserved characters. Send reserved characters by the URI can bring problems
! * ' ( ) ; : @ & = + $ , / ? # [ ]URI Length: You should not exceed 2000 characters
保留字符。通过 URI 发送保留字符会带来问题
! * ' ( ) ; : @ & = + $ , / ? # [ ]URI 长度:您不应超过 2000 个字符
回答by FunRob
I ran into this, too. I wanted to simulate hundreds of users with a Console app. When simulating only one user, everything was fine. But with more users came the Timeout exception all the time.
我也遇到了这个。我想使用控制台应用程序模拟数百名用户。当只模拟一个用户时,一切都很好。但是随着越来越多的用户出现超时异常。
Timeout occurs because by default the ConnectionLimit=2 to a ServicePoint (aka website). Very good article to read: https://venkateshnarayanan.wordpress.com/2013/04/17/httpwebrequest-reuse-of-tcp-connections/
发生超时是因为默认情况下 ConnectionLimit=2 到 ServicePoint(又名网站)。非常好的文章阅读:https: //venkateshnarayanan.wordpress.com/2013/04/17/httpwebrequest-reuse-of-tcp-connections/
What you can do is:
你可以做的是:
1) make more ConnectionGroups within a servicePoint, because ConnectionLimit is per ConnectionGroups.
1) 在一个 servicePoint 内创建更多的 ConnectionGroups,因为 ConnectionLimit 是每个 ConnectionGroups。
2) or you just simply increase the connection limit.
2)或者你只是简单地增加连接限制。
See my solution:
请参阅我的解决方案:
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's 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();
}

