package ar.com.javacuriosities.networking.tcp; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /* * Un socket representa un extremo (Endpoint) en una comunicación entre dos programas * corriendo en la red. * * Dependiendo del protocolo que usemos tendremos distintas capacidades * * TCP: * - Orientado a la conexión * - Garantiza un servicio extremo a extremo fiable * - Detecta/retransmite segmentos de datos perdidos o erróneos * - Detecta y descarta segmentos duplicados * - Ordena los segmentos en el destino y loas pasa de forma ordenada a la capa de aplicación * * UDP: * - Protocolo de transporte no orientado a la conexión * - No garantiza un servicio extremo a extremo fiable * - No controla la pérdida de paquetes, los errores o la duplicidad * * La cabecera usada por el protocolo TCP incluye 6 flags * SYN (Synchronize), ACK (Acknowledgement), RST (Reset), PSH (Push), URG (Urgent) y FIN (Urgent) * * Cada vez que iniciamos una conexión con un cliente se establece lo que se conoce como Handshake, * esto consta de los siguientes paso: * * Paso 1: * Aplicación A --> Envía un paquete con el flag SYN al puerto X de la aplicación B con un numero de secuencia * * A ------ [SYN secuencia:X] ----------------> B * * Paso 2: * Si el puerto esta abierto la aplicación B responde con los flag SYN y ACK también define un numero de secuencia inicial y envía el ACK con el * numero de secuencia de A mas 1. Si el puerto esta cerrado nos responden con RST y ACK. * * B ------ [SYN+ACK secuencia:Y ack:X+1] ----> A * * Paso 3: * La aplicación responde con un tercer paquete para confirmar la conexión con otro flag ACK * * A ------ [ACK secuencia:X+1 ack:Y+1] ------> B * */ public class Step1ServerSocketTCP { public static void main(String[] args) { try { /* * Creamos un socket el cual va a estar esperando conexiones * Parámetros: Parámetro 1 --> Indica el puerto que vamos a estar * escuchando Parámetro 2 --> Indica el tamaño máximo de la queue de * conexiones Parámetro 3 --> Indica la dirección IP del server * * Otra opción es crear un socket unbound y luego asociarlo usando * el método bind() */ try (ServerSocket serverSocket = new ServerSocket(4000, 50, InetAddress.getLocalHost())) { /* * Este timeout se utiliza para definir el máximo de tiempo a * esperar en el método accept(), el 0 indica infinito, si el * timeout es alcanzado se arroja la exception * "java.net.SocketTimeoutException: Accept timed out" */ serverSocket.setSoTimeout(0); /* * El método accept() es bloqueante por lo cual genera un * bloqueo hasta que llega una conexión */ while (true) { Socket clientSocket = serverSocket.accept(); // Pedimos el output stream para enviar mensajes al cliente OutputStream os = clientSocket.getOutputStream(); // Usamos un wrapper el cual nos permite escribir valores // primitivos de forma simple DataOutputStream dos = new DataOutputStream(os); // Write message dos.writeUTF("Hi!!!"); // Close output stream and client dos.close(); os.close(); clientSocket.close(); } } } catch (IOException e) { // Log and Handle exception e.printStackTrace(); } } }