我正在调用Apache服务器上托管的API来发布数据。我正在使用HttpWebRequest在C#中执行POST。
API在服务器上具有普通HTTP和安全层(HTTPS)PORT。当我调用HTTP URL时,它工作得非常好。但是,当我调用HTTPS时,它会给我超时异常(在GetRequestStream()函数中)。任何见解?我正在使用VS 2010,.Net framework 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();
编辑: 彼得建议的控制台程序运行正常。但是当我添加需要发布到API的数据(以JSON格式)时,它会抛出操作超时异常。这是我添加到基于控制台的应用程序的代码,它会抛出错误。
byte[] buffer = Encoding.ASCII.GetBytes(json_value);
request.ContentLength = buffer.Length;
答案 0 :(得分:13)
我遇到了同样的问题。好像它已经为我解决了。我查看了所有代码,确保为所有HttpWebResponse对象调用 webResponse.Close()和/或 responseStream.Close()。该文档表明您可以关闭流或HttpWebResponse对象。调用两者都没有害处,所以我做到了。不关闭响应可能会导致应用程序耗尽连接以便重用,这似乎会影响HttpWebRequest.GetRequestStream,就我在代码中可以看到的那样。
答案 1 :(得分:10)
我不知道这是否可以帮助您解决具体问题,但是您应该考虑在完成这些对象后对其进行处理。我最近正在做这样的事情,并且在使用语句中包装东西似乎为我清除了一堆超时异常。
using (var reqStream = request.GetRequestStream())
{
if (reqStream == null)
{
return;
}
//do whatever
}
还检查这些事情
您是否考虑过使用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());
}
}
编辑:
从控制台发出请求。
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 :(得分:2)
试试这个:
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个字符
答案 3 :(得分:1)
您可能需要设置超时属性,请在此处查看http://www.codeproject.com/Tips/69637/Setting-timeout-property-for-System-Net-WebClient
答案 4 :(得分:0)
我也遇到了这个。我想使用控制台应用程序模拟数百个用户。仅模拟一个用户时,一切都很好。但是随着越来越多的用户出现,超时异常一直存在。
发生超时是因为默认情况下,ServiceLimit(即网站)的ConnectionLimit = 2。 很棒的文章:https://venkateshnarayanan.wordpress.com/2013/04/17/httpwebrequest-reuse-of-tcp-connections/
您可以做的是:
1)在servicePoint内创建更多ConnectionGroup,因为ConnectionLimit是针对每个ConnectionGroup的。
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'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();
}