public ApplicationInstance(
			InetAddress inetAddress,
			int port,
			KeyPair<RSAKey> addressKeyPair,
			NetworkEndpointActionListener defaultNetworkEndpointsActionListener) throws ConnectionException {
		
		this.address = new Address<>(addressKeyPair);
		
		this.defaultNetworkEndpointActionListener = defaultNetworkEndpointsActionListener;
		
		try {
			
			Socket socket = new Socket(inetAddress, port);
			
			InputStream inputStream = socket.getInputStream();
			OutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
			
			this.streamByteBuf = new StreamByteBuf(inputStream, outputStream);
			
		} catch(IOException e) {
			throw new ConnectionException(e);
		}
		
		try {
			
			this.sentRevision = REVISION;
			
			for(;;) {
				
				this.receivedRevision = false;
				
				sendRevisionMessage(sentRevision);
				
				receiveMessage().callOnReceiveMethod(this);
				
				if(!this.receivedRevision) {
					throw new RevisionNegotiationConnectionException();
				}
				
				if(this.revision == this.sentRevision) {
					break;
				}
				
				switch(this.revision) {
				case 0: {
					this.sentRevision = this.revision;
					break;
				}
				default: {
					throw new RevisionNegotiationConnectionException();
				}
				}
				
			}
			
		} catch (BufException e) {
			throw new ConnectionException(e);
		} catch (ParseException e) {
			throw new ConnectionException(e);
		}
		
		this.start();
		
		if(addressKeyPair != null) {
			sendAddressPublicKeyMessage(addressKeyPair.getPublicKey());
			
			if(defaultNetworkEndpointsActionListener != null) {
				sendJoinDefaultNetworksMessage();
			}
		}
		
	}