I need to locally test some code that uses a WebClient object for communicating with an http server. For that purpose, I decided to write an incredibly simplistic mock server that reads some bytes from a binary file and sends them to the client. Here is the relevant server’s code:
public void Listen()
{
TcpClient client;
NetworkStream netStream;
listener.Start();
try
{
client = listener.AcceptTcpClient();
netStream = client.GetStream();
ReadData(netStream);
Console.WriteLine("Writing data, sequence 1");
WriteData(netStream, 1);
netStream.Close();
client.Close();
client = listener.AcceptTcpClient();
netStream = client.GetStream();
ReadData(netStream);
Console.WriteLine("Writing data, sequence 2");
WriteData(netStream, 2);
netStream.Close();
client.Close();
}
catch(Exception e)
{
}
}
private void WriteData(NetworkStream netStream, int sequence)
{
byte[] bytes = PrepareResponse(sequence); //get data from a file
netStream.Write(bytes, 0, bytes.Length);
}
With WebClient I use UploadString:
string response = client.UploadString(address + link, data);
So, the thing is, the WebClient apparently receives all the sent data, but throws a System.IO.Exception (“Unable to read data from the transport connection: The connection was closed.”) when I close the stream server-side. If I don’t close the stream, WebClient blocks and waits for the transfer to finish, despite all the data being received. I tried to substitute WebClient with WebRequest, and it also either throws an exception if the socket was closed server-side or blocks on stream.Read after reading all the data. What I find strange is that the first block of data I send to WebClient is an http 302 “Moved” response, which causes the WebClient to immediately send a GET request. Despite the fact that I send data identically two times, WebClient throws an exception only on the second response.
So – I need a way to correctly send the data and close the connection so it works with WebClient, and I would also like to know why does WebClient correctly handle the 302 response and throw an exception on the second response.
Thank you.
The answer was actually quite trivial – the second http response had “Transfer-Encoding: chunked” set in its headers, and I didn’t actually send the terminating zero-length chunk at the end of the response, thus WebClient was waiting for more data.