Saltar a contenido

Conceptos de redes

  • IP (Protocolo de Internet): Dirección única que identifica a un equipo en una red. Existen dos versiones principales: IPv4 (ej. 192.168.1.1) e IPv6 (ej. 2001:0db8:85a3::8a2e:0370:7334).
  • Puerto: Punto de acceso lógico para un servicio específico en un equipo. Se suele referenciar como IP:puerto.
    • 80: HTTP (Hypertext Transfer Protocol)
    • 443: HTTPS (HTTP Secure)
    • 22: SSH (Secure Shell)
    • 21: FTP (File Transfer Protocol) / SFTP (SSH File Transfer Protocol) usa comúnmente el puerto 22.
    • Los primeros 1024 puertos (0-1023) están reservados para servicios bien conocidos y generalmente requieren privilegios de administrador (root) para ser abiertos.
    • El rango máximo de puertos es de 0 a 65535 (2^16 puertos).
  • Tipos de interfaces de red virtuales (en contextos como virtualización):
    • Bridge (Puente): Conecta la máquina virtual directamente a la red física, dándole una IP independiente dentro de la misma subred.
    • NAT (Traducción de Direcciones de Red): Permite a la máquina virtual acceder a redes externas (como Internet) a través de la IP del host, pero sin poseer una dirección IP pública propia en la red externa.

Repaso de lenguajes de programación

El curso trabajará con dos lenguajes: C++ y Python.

Ejercicio de práctica

Desarrollar en C++ y en Python:

  1. Un programa que genere los números primos entre n y m, donde n <= m.
  2. Un programa que compruebe, para los valores n <= a, b, c <= m, que cumplan la relación pitagórica a² + b² = c².

Ejercicio 1

#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

// Función para determinar si un número es primo
bool esPrimo(int n) {
  if (n < 2) return false; // Los números menores a 2 no son primos
  if (n == 2) {
    return true; // 2 es el único número primo par
  }
  // Optimización: solo es necesario comprobar divisores hasta la raíz cuadrada de n
  for (int i = 2; i <= ceil(sqrt(n)); i++) {
    if (n % i == 0) {
      return false; // Si es divisible, no es primo
    }
  }
  return true; // Si no se encontraron divisores, es primo
}

// Función que retorna un vector con todos los primos en el rango [n, m]
vector<int> listaPrimos(int n, int m) {
  vector<int> sal = {}; // Vector para almacenar los resultados
  for (int i = n; i <= m; i++) {
    if (esPrimo(i)) {
      sal.push_back(i); // Agrega el número primo al vector
    }
  }
  return sal;
}

int main() {
  // Pruebas de la función esPrimo
  // Nota: %b no es un especificador estándar para bool en printf. Usar %d o imprimir directamente.
  printf("esPrimo(10): %d\n ", esPrimo(10)); // Debería ser 0 (false)
  printf("esPrimo(11): %d\n ", esPrimo(11)); // Debería ser 1 (true)
  printf("esPrimo(13): %d\n ", esPrimo(13)); // Debería ser 1 (true)

  // Obtener e imprimir primos entre 2 y 100
  vector<int> res = listaPrimos(2, 100);
  printf("Primos entre 2 y 100:\n");
  for (int i = 0; i < res.size(); i++) {
    printf("%i ", res[i]);
  }
  printf("\n");

  // Obtener e imprimir primos entre 1000 y 2000
  vector<int> resB = listaPrimos(1000, 2000);
  printf("Primos entre 1000 y 2000:\n");
  for (int i = 0; i < resB.size(); i++) {
    printf("%i ", resB[i]);
  }
  printf("\n");
  return 0; // Indica que el programa terminó correctamente
}
def esPrimo(num):
    """Determina si un número es primo."""
    if num < 2:
        return False  # Los números menores a 2 no son primos
    if num == 2:
        return True   # 2 es el único número primo par
    # Comprueba divisores desde 2 hasta la raíz cuadrada del número
    for i in range(2, int(num**0.5) + 1):
        if num % i == 0:
            return False  # Encontró un divisor, no es primo
    return True  # Es primo

def listaPrimos(n, m):
    """Retorna una lista con todos los números primos en el rango [n, m] inclusive."""
    primos = []
    for i in range(n, m + 1):
        if esPrimo(i):
            primos.append(i)  # Agrega el primo a la lista
    return primos

if __name__ == "__main__":
    # Bloque de ejecución principal
    print("Primos entre 2 y 100:", listaPrimos(2, 100))
    print("Primos entre 1000 y 2000:", listaPrimos(1000, 2000))

Ejercicio 2

#include <cstdio>
#include <vector>

using namespace std;

// Función que encuentra todas las ternas pitagóricas (a, b, c) en el rango [n, m]
vector<vector<int>> listaNumeros(int n, int m) {
  vector<vector<int>> sal; // Vector de vectores para almacenar las ternas
  // Tres bucles anidados para probar todas las combinaciones de a, b, c
  for (int a = n; a <= m; a++) {
    for (int b = n; b <= m; b++) {
      for (int c = n; c <= m; c++) {
        // Verifica la condición del teorema de Pitágoras
        if (a * a + b * b == c * c) {
          vector<int> terna = {a, b, c}; // Crea una terna
          sal.push_back(terna);          // Agrega la terna al resultado
        }
      }
    }
  }
  return sal;
}

int main() {
  // Encuentra ternas pitagóricas entre 1 y 100
  vector<vector<int>> res1 = listaNumeros(1, 100);
  printf("Ternas pitagóricas encontradas:\n");
  for (int i = 0; i < res1.size(); i++) {
    vector<int> terna = res1[i]; // Obtiene una terna
    printf("(");
    // Imprime los elementos de la terna
    for (int j = 0; j < terna.size(); j++) {
      printf("%i", terna[j]);
      if (j < terna.size() - 1) printf(", "); // Agrega coma entre elementos
    }
    printf(") ");
  }
  printf("\n");
  return 0;
}
def listaNumeros(n, m):
    """Retorna una lista de tuplas (a, b, c) que cumplen a² + b² = c² en el rango [n, m]."""
    sal = []
    # Bucles anidados para probar todas las combinaciones de a, b, c
    for a in range(n, m + 1):
        for b in range(n, m + 1):
            for c in range(n, m + 1):
                if a * a + b * b == c * c:
                    sal.append((a, b, c))  # Agrega la terna como una tupla
    return sal

if __name__ == "__main__":
    # Encuentra e imprime las ternas pitagóricas entre 1 y 100
    print("Ternas pitagóricas entre 1 y 100:", listaNumeros(1, 100))

Tabla de Resumen de Conceptos

Concepto Descripción Ejemplos / Notas
Dirección IP Identificador único para un dispositivo en una red. IPv4 (192.168.1.1), IPv6 (2001:db8::1).
Puerto Punto de acceso lógico para un servicio en un dispositivo. 80 (HTTP), 443 (HTTPS), 22 (SSH).
Puertos Reservados Puertos 0-1023, requieren privilegios elevados. Usados por servicios del sistema (SSH, HTTP).
Interfaz Bridge Conexión de red virtual que da IP independiente en la red física. La VM aparece como otro host en la LAN.
Interfaz NAT Conexión que comparte la IP del host para acceso externo. La VM accede a Internet sin IP pública propia.
Número Primo Número natural mayor que 1 divisible solo por 1 y sí mismo. 2, 3, 5, 7, 11...
Algoritmo de Primalidad Método para verificar si un número es primo. División por tentativa hasta \(\sqrt{n}\).
Terna Pitagórica Conjunto de tres enteros positivos (a, b, c) que cumplen \(a^2 + b^2 = c^2\). (3, 4, 5), (5, 12, 13).
Búsqueda por Fuerza Bruta Algoritmo que prueba todas las combinaciones posibles. Usado en el ejercicio 2 con tres bucles for.

Comentarios Adicionales

  • Redes: Es crucial entender la diferencia entre una dirección IP (identidad del host) y un puerto (identidad del servicio/proceso en ese host). Los firewalls a menudo filtran tráfico basándose en reglas de IP y puerto. En entornos de virtualización, la elección entre Bridge y NAT depende de si se necesita que la máquina virtual sea direccionable directamente desde la red local o no.
  • Programación - Ejercicio 1 (Primos): El algoritmo de verificación de primalidad utilizado es correcto pero ineficiente para números muy grandes. Existen algoritmos más avanzados y eficientes, como la Criba de Eratóstenes para generar primos en un rango, o pruebas probabilísticas como Miller-Rabin para números extremadamente grandes.
  • Programación - Ejercicio 2 (Ternas Pitagóricas): La solución implementada tiene una complejidad temporal de \(O((m-n)^3)\), lo que la hace muy costosa para rangos grandes. Se pueden aplicar optimizaciones matemáticas, como generar ternas usando fórmulas basadas en parámetros (como la fórmula de Euclides para ternas primitivas) o, al menos, evitar calcular c desde n y en su lugar calcularlo como \(c = \sqrt{a^2 + b^2}\) y verificar si es un entero dentro del rango, reduciendo la complejidad a \(O((m-n)^2)\).
  • Comparación C++/Python: El código en C++ es de más bajo nivel, requiere gestión explícita de tipos y memoria (vectores), y es generalmente más rápido en ejecución. Python es más conciso, legible y con estructuras de datos de alto nivel (listas, tuplas) integradas, lo que favorece la rapidez de desarrollo. La elección del lenguaje depende del contexto: rendimiento crítico (C++) vs. prototipado o scripting (Python).