//
// 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.
//
// 
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

namespace Bench
{
	/// <summary>
	/// Podsumowanie dla TcpTest.
	/// </summary>
	public class TcpTest : NetworkTest
	{
		public TcpTest(string server, int port, int numberOfPackets, int packetSize) :
			   base(server, port, numberOfPackets, packetSize)
		{
		}
		private Socket GetSocket(string host, int port) 
		{
			Socket s = null;
			IPHostEntry iphe = Dns.Resolve(host);
			// Pętla dla wszystkich adresów, a nie tylko
			// pierwszy adres. 
			foreach(IPAddress ipa in iphe.AddressList) 
			{
				IPEndPoint ipe = new IPEndPoint(ipa, port);
		
				// Użycie AddressFamily, która stanowi część
				// punktu końcowego. 
				// AddressFamily.InterNetwork ogranicza
				// do IPv4
				Socket ts = new Socket(ipe.AddressFamily,
					                   SocketType.Stream,
					                   ProtocolType.Tcp);
				try 
				{
					// Zwrócenie pierwszego gniazda, 
					// z którym można nawiązać połączenie.
					ts.Connect(ipe);
					s = ts;
					break;
				} 
				catch (ArgumentNullException ae)
				{
					Console.WriteLine("Wyjątek ArgumentNullException: " + ae.ToString());
				}
				catch (SocketException se)
				{				
					Console.WriteLine("Wyjątek SocketException: " + se.ToString());
				}
				catch (Exception e) 
				{
					Console.WriteLine("Połączenie nie powiodło się: " + e.ToString());
				}
			}
			return s;
		}
		public override void Start()
		{
			Socket s = GetSocket(Server, Port);
			if(s == null)
				return;

			byte[] writeBuffer = new byte[PacketSize];
			byte[] readBuffer = new byte[PacketSize];
			int nTransmitted;
			int nReceived;
			int nTotalReceived;

			TransmitByteCount = 0;
			ReceivedByteCount = 0;

			// Wysłanie losowych bajtów
			s.Send(writeBuffer, 0, 100, SocketFlags.None);
			s.Receive(readBuffer, 0, 100, SocketFlags.None);

			// Wykonanie testu
			int counterStart = Environment.TickCount;
			StartCounters();
			int counterStop = Environment.TickCount;
			Debug.WriteLine("Start licznika " + Convert.ToString(counterStop - counterStart));
			int startTime = Environment.TickCount;
			for(int i = 0; i < NumberOfPackets; i++)
			{
				nTransmitted = s.Send(writeBuffer, 0, writeBuffer.Length, SocketFlags.None);
				TransmitByteCount += nTransmitted;
				for(nReceived = 0, nTotalReceived = 0; nTotalReceived < nTransmitted;)
				{
					nReceived = s.Receive(readBuffer, nReceived, nTransmitted - nTotalReceived, SocketFlags.None);
					ReceivedByteCount += nReceived;
					nTotalReceived += nReceived;
				}
			}
			int endTime = Environment.TickCount;
			counterStart = Environment.TickCount;
			StopCounters();
			counterStop = Environment.TickCount;
			Debug.WriteLine("Zatrzymanie licznika " + Convert.ToString(counterStop - counterStart));

			Elapsed = endTime - startTime;

			s.Close();
		}
	}
}
