// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0
using System;
+using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
+using System.Threading.Tasks;
using NUnit.Framework;
+using MonoTests.Helpers;
namespace MonoTests.System.Net {
[TestFixture]
[SetUp]
public void SetUp () {
- port = new Random ().Next (7777, 8000);
+ port = NetworkHelpers.FindFreePort ();
}
[Test]
Event.Close ();
}
}
+
+ [Test]
+ public void ConnectionReuse ()
+ {
+ var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
+
+ HttpListener listener = new HttpListener ();
+ listener.Prefixes.Add (uri);
+ listener.Start ();
+
+ IPEndPoint expectedIpEndPoint = CreateListenerRequest (listener, uri);
+
+ Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse1");
+ Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse2");
+ }
+
+ public IPEndPoint CreateListenerRequest (HttpListener listener, string uri)
+ {
+ IPEndPoint ipEndPoint = null;
+ var mre = new ManualResetEventSlim ();
+ listener.BeginGetContext (result => {
+ ipEndPoint = ListenerCallback (result);
+ mre.Set ();
+ }, listener);
+
+ var request = (HttpWebRequest) WebRequest.Create (uri);
+ request.Method = "POST";
+
+ // We need to write something
+ request.GetRequestStream ().Write (new byte [] {(byte)'a'}, 0, 1);
+ request.GetRequestStream ().Dispose ();
+
+ // Send request, socket is created or reused.
+ var response = request.GetResponse ();
+
+ // Close response so socket can be reused.
+ response.Close ();
+
+ mre.Wait ();
+
+ return ipEndPoint;
+ }
+
+ public static IPEndPoint ListenerCallback (IAsyncResult result)
+ {
+ var listener = (HttpListener) result.AsyncState;
+ var context = listener.EndGetContext (result);
+ var clientEndPoint = context.Request.RemoteEndPoint;
+
+ // Disposing InputStream should not avoid socket reuse
+ context.Request.InputStream.Dispose ();
+
+ // Close OutputStream to send response
+ context.Response.OutputStream.Close ();
+
+ return clientEndPoint;
+ }
+
+ [Test]
+ public void HttpClientIsDisconnectedCheckForWriteException()
+ {
+ string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
+
+ AutoResetEvent exceptionOccuredEvent = new AutoResetEvent (false);
+ HttpListener listener = new HttpListener {
+ IgnoreWriteExceptions = false
+ };
+ listener.Prefixes.Add (uri);
+ listener.Start ();
+ listener.BeginGetContext (result =>
+ {
+ HttpListenerContext context = listener.EndGetContext (result);
+ context.Response.SendChunked = true;
+ context.Request.InputStream.Close ();
+
+ var bytes = new byte [1024];
+ using(Stream outputStream = context.Response.OutputStream) {
+ try {
+ while (true)
+ outputStream.Write (bytes, 0, bytes.Length);
+ } catch {
+ exceptionOccuredEvent.Set ();
+ }
+ }
+ }, null);
+
+ Task.Factory.StartNew (() =>
+ {
+ var webRequest = (HttpWebRequest)WebRequest.Create (uri);
+ webRequest.Method = "POST";
+ webRequest.KeepAlive = false;
+ Stream requestStream = webRequest.GetRequestStream ();
+ requestStream.WriteByte (1);
+ requestStream.Close ();
+ using (WebResponse response = webRequest.GetResponse ())
+ using (Stream stream = response.GetResponseStream ()) {
+ byte[] clientBytes = new byte [1024];
+ Assert.IsNotNull (stream, "#01");
+ stream.Read (clientBytes, 0, clientBytes.Length);
+ }
+ });
+
+ Assert.IsTrue (exceptionOccuredEvent.WaitOne (15 * 1000), "#02");
+ }
}
}
-#endif