public static void main(String[] args) throws Exception {

		final VirtualSocketAddress serverAddr;
		final VirtualSocketAddress clientAddr;

		serverAddr = new VirtualSocketAddress("localhost", 50200);
		clientAddr = new VirtualSocketAddress("localhost", 50201);
		
		if(virtual) {
			host = new VirtualHost("localhost", net);
		}


		Thread serverThread = new Thread() {

			public void run() {
				
				SocketFactory servFact;
				try {
					servFact = buildSocketFactory();
				} catch (NetworkException e1) {
					e1.printStackTrace();
					return;
				}
				try {

					ServerSocketInterface serv =
						servFact.newServerSocket(serverAddr.getPort());
					printMessage("ServerSocket bound.");

					SocketInterface sock = serv.accept();
					serv.close();
					printMessage("Remote host: "+sock.getRemoteSocketAddress());
					
					sock.setSoTimeout(TIME_OUT);
					
					// Data test
					InputStream dis = new BufferedInputStream(sock.getInputStream());
					OutputStream ackStream = sock.getOutputStream();
					byte[] buf = new byte[packetSize * CLIENT_SERVER_MULT];
					for(int i = 0; i < MSG_TO_SEND; ++i) {

						printMessage("Receiving message n°"+i+" from client.");
						for(int j = 0; j < CLIENT_SERVER_MULT; ++j)
							dis.read(buf, j * packetSize, packetSize);
						printMessage("Received message n°"+i+" from client");
						ackStream.write(0);
						ackStream.flush();

					}
					
					
					// Object test
					ObjectInputStream ois = new ObjectInputStream(sock.getInputStream());
					String str = (String) ois.readObject();
					printMessage("Received String "+str);

					sock.close();

				} catch (Exception e) {
					printMessage(e);
				}

			}
			
			private void printMessage(String str) {
				VirtualSocketTest.printMessage("[Server] "+str);
			}
			
			private void printMessage(Throwable t) {
				VirtualSocketTest.printMessage("[Server] Exception:");
				VirtualSocketTest.printMessage(t);
			}
			
		};

		Thread clientThread = new Thread() {
			
			public void run() {
				
				SocketFactory clientFact;
				try {
					clientFact = buildSocketFactory();
				} catch (NetworkException e1) {
					e1.printStackTrace();
					return;
				}

				try {

					SocketInterface sock = clientFact.newSocket();
					sock.connect(serverAddr, TIME_OUT);
					
					printMessage("Remote host: "+sock.getRemoteSocketAddress());
					
					sock.setSoTimeout(TIME_OUT);
					
					// Data test
					OutputStream dos = sock.getOutputStream();
					InputStream ackStream = new BufferedInputStream(sock.getInputStream());
					byte[] msg = new byte[packetSize];
					Random r = new Random(System.currentTimeMillis());
					for(int i = 0; i < MSG_TO_SEND; ++i) {

						for(int j = 0; j < CLIENT_SERVER_MULT; ++j) {
							r.nextBytes(msg);
							dos.write(msg);
						}
						printMessage("Sent message n°"+i+" to server.");
						printMessage("Waiting ack from server.");
						ackStream.read();

					}
					
					
					// Object test
					ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(sock.getOutputStream()));
					oos.writeObject("test");
					oos.close();

					sock.close();

				} catch (Exception e) {
					printMessage(e);
				}

			}
			
			private void printMessage(String str) {
				VirtualSocketTest.printMessage("[client] "+str);
			}
			
			private void printMessage(Throwable t) {
				VirtualSocketTest.printMessage("[client] Exception:");
				VirtualSocketTest.printMessage(t);
			}
			
		};
		

		serverThread.start();
		Thread.sleep(1000);
		clientThread.start();
		
		serverThread.join();
		clientThread.join();

	}