Rothmans
asked on
WebException thrown on a HttpWebRequest.GetResponse() call
Hi,
I have a problem using HttpWebRequest class.
I create an application, which communicates with a network device (not a PC), which has a built in HTTP 1.1 server listening on port 80. For some requests, which I send to the server it answers with a short byte sequence:
HTTP/1.1 200 OK\r\n
and that's it, no more data (I check network traffic using Ethereal network monitor).
In case of such response from the server, I get a WebException on a call to HttWebRequest.GetResponse( ) method saying: "The underlying connection was closed: An unexpected error occured on a receive". If there are some data coming from server, then GetResponse() method returns instance of HttpWebResponse properly.
here is a code, where I get a WebException:
HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(TargetUr iString);
hwr.Timeout = 10000;
hwr.Method = "POST";
hwr.UserAgent = "AddressEditor";
hwr.ContentLength = buf.Length;
hwr.KeepAlive = true;
HttpWebResponse hwResponse = null;
Stream sr = null;
try
{
// Write data
Stream s = hwr.GetRequestStream();
s.Write(buf,0,buf.Length);
s.Close();
// Read response
hwResponse = (HttpWebResponse) hwr.GetResponse(); // WebException is thrown here !!!
if(hwResponse.StatusCode == HttpStatusCode.OK)
{
if(hwr.HaveResponse)
{
sr = hwResponse.GetResponseStre am();
int offset=0;
int remaining = buf.Length;
while (remaining > 0)
{
int read = sr.Read(buf, offset, remaining);
if (read <= 0)
break;
remaining -= read;
offset += read;
}
}
}
}
catch(WebException we)
{
Console.WriteLine(we.Messa ge);
}
finally
{
if(sr != null)
sr.Close();
if(hwResponse != null)
hwResponse.Close();
}
Actually, I am not completely sure, whether the problem is im my code, .NET framework or device HTTP server, because exception occurs immediately after a call to GetResponse() and the device usually answers with "HTTP/1.1 200 OK\r\n" after a approximately 5 seconds timeout, because of processing of input data. So the GetResponse() does not wait for response and just throws exception. It does not happen with this code when the server returns some data.
Could you please give me a hint:
1) Am I correctly using HttpWebrequest to write data to the remote server?
2) How to make my code block and wait untill "HTTP/1.1 200 OK\r\n" response comes from the server? (The server becomes unavailable untill it processes all input data sent by me and I can not send next requests to it untill this one ends with 200 OK)
Thank you for any help, it is really apreciated.
Sergey
I have a problem using HttpWebRequest class.
I create an application, which communicates with a network device (not a PC), which has a built in HTTP 1.1 server listening on port 80. For some requests, which I send to the server it answers with a short byte sequence:
HTTP/1.1 200 OK\r\n
and that's it, no more data (I check network traffic using Ethereal network monitor).
In case of such response from the server, I get a WebException on a call to HttWebRequest.GetResponse(
here is a code, where I get a WebException:
HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(TargetUr
hwr.Timeout = 10000;
hwr.Method = "POST";
hwr.UserAgent = "AddressEditor";
hwr.ContentLength = buf.Length;
hwr.KeepAlive = true;
HttpWebResponse hwResponse = null;
Stream sr = null;
try
{
// Write data
Stream s = hwr.GetRequestStream();
s.Write(buf,0,buf.Length);
s.Close();
// Read response
hwResponse = (HttpWebResponse) hwr.GetResponse(); // WebException is thrown here !!!
if(hwResponse.StatusCode == HttpStatusCode.OK)
{
if(hwr.HaveResponse)
{
sr = hwResponse.GetResponseStre
int offset=0;
int remaining = buf.Length;
while (remaining > 0)
{
int read = sr.Read(buf, offset, remaining);
if (read <= 0)
break;
remaining -= read;
offset += read;
}
}
}
}
catch(WebException we)
{
Console.WriteLine(we.Messa
}
finally
{
if(sr != null)
sr.Close();
if(hwResponse != null)
hwResponse.Close();
}
Actually, I am not completely sure, whether the problem is im my code, .NET framework or device HTTP server, because exception occurs immediately after a call to GetResponse() and the device usually answers with "HTTP/1.1 200 OK\r\n" after a approximately 5 seconds timeout, because of processing of input data. So the GetResponse() does not wait for response and just throws exception. It does not happen with this code when the server returns some data.
Could you please give me a hint:
1) Am I correctly using HttpWebrequest to write data to the remote server?
2) How to make my code block and wait untill "HTTP/1.1 200 OK\r\n" response comes from the server? (The server becomes unavailable untill it processes all input data sent by me and I can not send next requests to it untill this one ends with 200 OK)
Thank you for any help, it is really apreciated.
Sergey
ASKER
The server in the device is written not by me and I have almost no information describing it's behaviour and no access to the code.
Sergey.
Sergey.
Well, it sounds like you are not forming the WebRequest correctly, and unless you can find the right format, then it will be virtually impossible to fix.
You did say that you are getting some requests back successfully. What is different between the requests that succeed and the ones that fail?
Bob
You did say that you are getting some requests back successfully. What is different between the requests that succeed and the ones that fail?
Bob
ASKER
Well, there are two entry points for me in the device HTTP server:
1) /cgi-bin/get.cgi
This script (?) returns data describing device settings
2) /cgi-bin/set.cgi
This script accepts settings (same as for get.cgi), which I (user) want to propagate to the device
Format of request to the first script is:
<method POST>
<HTTP Headers>
User-Agent: <user agent name>
Content-Length: <length of >
\r\n
<binary data defining settings, which I want to retireve>
<two trailing zeros>
Server response for this case is:
HTTP/1.1 200 OK\r\n
\r\n
<binary data describing device settings>
<two trailing zeros>
Format of request to the second script is:
<method POST>
<HTTP Headers>
User-Agent: <user agent name>
Content-Length: <length of >
\r\n
<binary data describing settings, which I want to set>
<two trailing zeros>
Server response for this case is:
HTTP/1.1 200 OK\r\n
I use the same code (see above) for both cases.
For the first case GetResponse() returns HttpResponse instance, from where I can get response binary data, properly, no exception is thrown.
For the second case settings ARE ACCEPTED by the device and ARE PROCESSED properly, but GetResponse throws mentioned above exception.
Of course, I could just ignore this exception, because I do not need actually response data, but...
I need to send several requests of second type to the device in order to complete my task.
It happens that the device processes input data several seconds and during this period device is unavailable. Any attempt to establish HTTP connection to it fails with HTTP server response "503 Service Unavailable". Therefore, I can not proceed with next requests.
That's why I acctually need to know when the device finishes accepting and processing input data (returning 200 OK Status Line), because otherwise next calls will fail and timeouts (how much time the device needs to process data) are undefined and may vary.
PS: It seems that "Expect: 100-Continue" mode is not supported by the device HTTP server.
1) /cgi-bin/get.cgi
This script (?) returns data describing device settings
2) /cgi-bin/set.cgi
This script accepts settings (same as for get.cgi), which I (user) want to propagate to the device
Format of request to the first script is:
<method POST>
<HTTP Headers>
User-Agent: <user agent name>
Content-Length: <length of >
\r\n
<binary data defining settings, which I want to retireve>
<two trailing zeros>
Server response for this case is:
HTTP/1.1 200 OK\r\n
\r\n
<binary data describing device settings>
<two trailing zeros>
Format of request to the second script is:
<method POST>
<HTTP Headers>
User-Agent: <user agent name>
Content-Length: <length of >
\r\n
<binary data describing settings, which I want to set>
<two trailing zeros>
Server response for this case is:
HTTP/1.1 200 OK\r\n
I use the same code (see above) for both cases.
For the first case GetResponse() returns HttpResponse instance, from where I can get response binary data, properly, no exception is thrown.
For the second case settings ARE ACCEPTED by the device and ARE PROCESSED properly, but GetResponse throws mentioned above exception.
Of course, I could just ignore this exception, because I do not need actually response data, but...
I need to send several requests of second type to the device in order to complete my task.
It happens that the device processes input data several seconds and during this period device is unavailable. Any attempt to establish HTTP connection to it fails with HTTP server response "503 Service Unavailable". Therefore, I can not proceed with next requests.
That's why I acctually need to know when the device finishes accepting and processing input data (returning 200 OK Status Line), because otherwise next calls will fail and timeouts (how much time the device needs to process data) are undefined and may vary.
PS: It seems that "Expect: 100-Continue" mode is not supported by the device HTTP server.
ASKER
After some reading HTTP RFC I came to one suspicion.
RFC says that in case when there is no data returned by the server the response should be "204 No Content".
Could it be that GetResponse waits for a data because "200 OK" response acquired and for the second described scenario "200 OK" is not the right answer because there are no data following this response?
RFC says that in case when there is no data returned by the server the response should be "204 No Content".
Could it be that GetResponse waits for a data because "200 OK" response acquired and for the second described scenario "200 OK" is not the right answer because there are no data following this response?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That would be a solution if I would not need to make several requests one after another.
If I put WebRequest into try&catch block, then the next request will fail because device is busy.
Sergey
If I put WebRequest into try&catch block, then the next request will fail because device is busy.
Sergey
I mean something like this:
HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(TargetUr iString);
hwr.Timeout = 10000;
hwr.Method = "POST";
hwr.UserAgent = "AddressEditor";
hwr.ContentLength = buf.Length;
hwr.KeepAlive = true;
HttpWebResponse hwResponse = null;
Stream sr = null;
try
{
// Write data
Stream s = hwr.GetRequestStream();
s.Write(buf,0,buf.Length);
s.Close();
// Read response
try {
hwResponse = (HttpWebResponse) hwr.GetResponse(); // WebException is thrown here !!!
}
catch {}
if(hwResponse.StatusCode == HttpStatusCode.OK)
{
if(hwr.HaveResponse)
{
sr = hwResponse.GetResponseStre am();
int offset=0;
int remaining = buf.Length;
while (remaining > 0)
{
int read = sr.Read(buf, offset, remaining);
if (read <= 0)
break;
remaining -= read;
offset += read;
}
}
}
}
catch(WebException we)
{
Console.WriteLine(we.Messa ge);
}
finally
{
if(sr != null)
sr.Close();
if(hwResponse != null)
hwResponse.Close();
}
Bob
HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(TargetUr
hwr.Timeout = 10000;
hwr.Method = "POST";
hwr.UserAgent = "AddressEditor";
hwr.ContentLength = buf.Length;
hwr.KeepAlive = true;
HttpWebResponse hwResponse = null;
Stream sr = null;
try
{
// Write data
Stream s = hwr.GetRequestStream();
s.Write(buf,0,buf.Length);
s.Close();
// Read response
try {
hwResponse = (HttpWebResponse) hwr.GetResponse(); // WebException is thrown here !!!
}
catch {}
if(hwResponse.StatusCode == HttpStatusCode.OK)
{
if(hwr.HaveResponse)
{
sr = hwResponse.GetResponseStre
int offset=0;
int remaining = buf.Length;
while (remaining > 0)
{
int read = sr.Read(buf, offset, remaining);
if (read <= 0)
break;
remaining -= read;
offset += read;
}
}
}
}
catch(WebException we)
{
Console.WriteLine(we.Messa
}
finally
{
if(sr != null)
sr.Close();
if(hwResponse != null)
hwResponse.Close();
}
Bob
ASKER
Anyway thank you for a hint.
I try now to catch "503 Service Unavailable" response and repeat a request attempt in this case. Seems it is possible.
Sergey.
I try now to catch "503 Service Unavailable" response and repeat a request attempt in this case. Seems it is possible.
Sergey.
ASKER
I succeeded to avoid the problem handling "503 Service Unavaible" response.
Thenk you, Bob, for your help.
Sergey.
Thenk you, Bob, for your help.
Sergey.
Bob