//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
namespace NetClassAsyncSender
{
	using System;
	using System.Net;
	using System.IO;
	using System.Text;
	using System.Threading;
	
	public class RequestState
	{
		private StringBuilder _RequestData;
		internal byte[] _bufferRead;
		public HttpWebRequest Request;
		public Stream ResponseStream;
		
		public RequestState()
		{
			_bufferRead = new byte[1024];
			_RequestData = new StringBuilder();
			Request = null;
			ResponseStream = null;
		}
     
		public StringBuilder RequestData
		{
			get 
		{return _RequestData;}
			set 
		{_RequestData = value;}
		}
	}
	
	public class NCAsyncRequestSender
	{
		public static ManualResetEvent allDone = null;
		public static int NumRequests = 100;
		public static int NumConnections = 4;


		public static int GlobalCallbackCounter = 0;
		public static int Main(string[] args)
		{

		for (int j=0;j<5;j++)
			{
			int start = 0;
			int end = 0;
			int total = 0;
			GlobalCallbackCounter=0;			
			allDone = new ManualResetEvent(false);
			start = Environment.TickCount;
		
			try
			{	
				GetPages();
			}
			catch(WebException webex)
			{
				Console.WriteLine(webex.ToString());			
			}
			
			allDone.WaitOne();
			end = Environment.TickCount;				
			total = end-start;
			
			Console.WriteLine(total);
			}
			return 0;
		}

		public static void GetPages()
		{			

			Uri address = new Uri("http://homer.pickatime.com/lanceo/default.htm");
			//Uri address = new Uri("http://lanceo3/services/readme.htm");			
			
            int i;
           	for (i=0; i<NumRequests; i++)
 		    {

			HttpWebRequest	Request = (HttpWebRequest)WebRequest.Create(address);
			RequestState requestState = new RequestState();
			Request.Proxy = new WebProxy("http://itgproxy");
			Request.ServicePoint.ConnectionLimit = NumConnections;
			Request.Pipelined = false; 
			    requestState.Request = Request;
	            Request.BeginGetResponse(new AsyncCallback(RespCallback), requestState);
		    }			
           		
			return;			
		}
		
		private static void RespCallback(IAsyncResult ar)
		{
			GlobalCallbackCounter++;
			
			RequestState rs = (RequestState)ar.AsyncState;			
			HttpWebRequest req = rs.Request;
			req.ServicePoint.ConnectionLimit = NumConnections;			
			WebResponse theResponse = (WebResponse) req.EndGetResponse(ar);
			const int BUFFER_SIZE = 1024;									
			
			Stream ResponseStream = theResponse.GetResponseStream();
			rs.ResponseStream = ResponseStream;
			IAsyncResult iarRead = ResponseStream.BeginRead(rs._bufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
		}

		private static void ReadCallBack(IAsyncResult asyncResult)
		{
			RequestState rs = (RequestState)asyncResult.AsyncState;
			Stream responseStream = rs.ResponseStream;
			int read = responseStream.EndRead( asyncResult );

			if (read > 0)
			{
				rs.RequestData.Append(Encoding.ASCII.GetString(rs._bufferRead, 0, read));			
				
				IAsyncResult ar = responseStream.BeginRead( rs._bufferRead, 0, 1024, new AsyncCallback(ReadCallBack), rs);
				//IAsyncResult ar2 = responseStream.BeginRead( rs._bufferRead, 0, 1024, new AsyncCallback(ReadCallBack), rs);
			}
			else
			{
				if(rs.RequestData.Length>1)
				{
					// W tym momencie można już coś zrobić ze stroną,
					// ponieważ wszystkie dane zostały odczytane.
					//string strContent;						
					//strContent = rs.RequestData.ToString();
					//Console.Write(strContent.Length.ToString());
					//Console.Write(".");
				}
				
				responseStream.Close();
				
				if (GlobalCallbackCounter==NumRequests)
				{
					allDone.Set();
				}				
			}
			return;
		}
	}
}
