Socket, también conocido como sockets, es una de las tecnologías básicas para la comunicación de la red informática. Hoy, la mayoría de los software basado en la web, como navegadores, herramientas de mensajería instantánea e incluso descargas P2P, se implementan en función de Socket. Este artículo presentará la programación de socket basada en TCP/IP y cómo escribir un programa de cliente/servidor.
Postre previo a la cena
El sistema de entrada y salida de UNIX (IO) sigue plantillas de operación como la lectura-escritura de lectura abierta. Antes de que un proceso de usuario realice operaciones IO, debe llamar a la llamada para especificar y obtener permisos para que el archivo o dispositivo se opere para leer o escribir. Una vez que se abre el objeto de operación IO, el proceso del usuario puede realizar una o más operaciones de lectura o escritura en el objeto. La operación de lectura se utiliza para leer datos de los objetos de operación IO y pasar los datos al proceso del usuario. La operación de escritura se utiliza para pasar (escribir) datos en los procesos de usuario a los objetos de operación IO. Después de completar todas las operaciones de lectura y escritura, el proceso del usuario debe llamar a Close para notificar al sistema que completa su uso del objeto IO.
Cuando UNIX comenzó a admitir InterProcess Communication (IPC), la interfaz IPC fue diseñada para ser similar a la interfaz de operación del archivo IO. En UNIX, un proceso tendrá un conjunto de descriptores IO que se pueden leer y escribir. El descriptor IO puede ser un archivo, dispositivo o un canal de comunicación (socket). Un descriptor de archivo consta de tres partes: crear (abrir el socket), leer y escribir datos (aceptando y enviando a socket) y destruyendo (cloque de cierre).
En los sistemas UNIX, la versión similar a BSD de la interfaz IPC se implementa como una capa sobre los protocolos TCP y UDP. El destino del mensaje está representado por la dirección del socket. Una dirección de socket es un identificador de comunicación compuesto por una dirección de red y un número de puerto.
Las operaciones de comunicación entre procesos requieren un par de enchufes. La comunicación entre procesos se realiza mediante la transmisión de datos entre un enchufe en un proceso y otro socket en otro proceso. Cuando se ejecuta y envía un mensaje, el mensaje se pone en cola en el socket en el extremo de envío hasta que el protocolo de red de nivel inferior envía los mensajes. Cuando el mensaje llega al socket en el extremo receptor, también estará en una cola hasta que el proceso en el extremo receptor reciba el mensaje.
Comunicación TCP y UDP
Con respecto a la programación de socket, tenemos dos protocolos de comunicación para elegir. Uno es la comunicación de datagrama, la otra es la comunicación de flujo.
Comunicación de datagrama
El protocolo de comunicación de datagrama es lo que a menudo llamamos UDP (protocolo de datos del usuario). UDP es un protocolo sin conexión, lo que significa que cada vez que enviamos datagramas, necesitamos enviar el descriptor de socket de la máquina nativa y el descriptor de socket del receptor al mismo tiempo. Por lo tanto, necesitamos enviar datos adicionales cada vez que nos comunicemos.
Comunicación de transmisión
El protocolo de comunicación de la corriente, también conocido como TCP (protocolo de control de transferencia) también se llama TCP (protocolo de control de transferencia). A diferencia de UDP, TCP es un protocolo basado en la conexión. Antes de usar la comunicación de transmisión, debemos establecer una conexión entre el par de comunicación de enchufes. Uno de los sockets sirve como servidor para escuchar las solicitudes de conexión. El otro realiza solicitudes de conexión como cliente. Una vez que los dos enchufes hayan establecido una conexión, pueden transferir datos en unidireccional o en dos vías.
Después de leer esto, tenemos algunas preguntas sobre si usamos UDP o TCP para la programación de socket. La elección de la programación de socket en función de qué protocolo se basa en su escenario de aplicación específico depende de su programa específico de cliente cliente. A continuación analizamos brevemente la diferencia entre los protocolos TCP y UDP, lo que puede ayudarlo a elegir mejor cuál usar.
En UDP, cada vez que se envía un datagrama, el descriptor de socket de la máquina nativa y el descriptor de socket del receptor deben incluirse. Dado que TCP es un protocolo basado en la conexión, se debe establecer una conexión entre los pares de socket de comunicación antes de la comunicación, por lo que habrá una programación de conexión que requiere mucho tiempo en el protocolo TCP.
En UDP, los datos de datagrama tienen un límite de 64 kb en tamaño. No existe tal restricción en TCP. Una vez que el par de la comunicación TCP establece una conexión, la comunicación entre ellos es similar a un flujo de IO, y todos los datos se leerán en el orden en que se acepta.
UDP es un protocolo poco confiable, y los datagramas enviados no son necesariamente aceptados por el socket receptor en el orden en que se envían. Entonces TCP es un protocolo confiable. El orden de los paquetes recibidos por el extremo receptor es consistente con el orden de los paquetes en el extremo de envío.
En resumen, TCP es adecuado para servicios de red como Remote Login (RLogin, Telnet) y la transferencia de archivos (FTP). Porque el tamaño de estos datos que deben transmitirse es incierto. UDP es más simple y ligero que TCP. UDP se utiliza para implementar algunos servicios que son más en tiempo real o que no tengan importancia de la pérdida de paquetes. La tasa de pérdida de paquetes de UDP en LAN es relativamente baja.
Programación de sockets en Java
En la siguiente sección, explicaré cómo usar Socket para escribir programas de clientes y servidores a través de algunos ejemplos.
Nota: En el siguiente ejemplo, usaré la programación de socket basada en el protocolo TCP/IP, porque este protocolo es mucho más utilizado que UDP/IP. Y todas las clases relacionadas con el socket se encuentran debajo del paquete Java.net, por lo que debemos introducir este paquete cuando estamos haciendo programación de socket.
Escritura de clientes
Encender el enchufe
Si está en el lado del cliente, debe escribir el siguiente código para abrir un socket.
String host = "127.0.0.1"; int port = 8919; socket client = new Socket (host, puerto);
En el código anterior, el host es la máquina a la que el cliente necesita conectarse, y el puerto es el puerto utilizado por el servidor para escuchar la solicitud. Al seleccionar un puerto, una cosa a la que debe prestar atención es que los puertos como 0 ~ 1023 han sido reservados por el sistema. Estos puertos son utilizados por algunos servicios de uso común, como Mail, FTP y HTTP. Cuando escriba código del lado del servidor y seleccione un puerto, seleccione un puerto mayor a 1023.
Escribir datos
Lo siguiente es escribir los datos de la solicitud. Obtenemos el objeto OutputStream del objeto Socket del cliente y luego escribimos los datos. Muy similar al código de procesamiento del archivo IO.
Public Class Clientsocket {public static void main (string args []) {string host = "127.0.0.1"; Int Port = 8919; intente {Socket Client = new Socket (host, puerto); Escritor escritor = nuevo outputStreamWriter (Client.getOutputStream ()); Writer.write ("Hola desde el cliente"); escritor.flush (); escritor.close (); client.close (); } catch (ioException e) {E.PrintStackTrace (); }}}Cerrar el objeto IO
Similar al archivo IO, después de leer y escribir datos, debemos cerrar el objeto IO para garantizar la versión correcta de los recursos.
Escritura del lado del servidor
Abra el zócalo del lado del servidor
int port = 8919; ServerSocket Server = new Serversocket (puerto); socket Socket = server.accept ();
El código anterior crea un socket del lado del servidor y luego llama al método de aceptación para escuchar y obtener el socket de solicitud del cliente. El método de aceptación es un método de bloqueo que espera el bloqueo hasta que se realice una conexión entre el servidor y el cliente.
Leer datos
Obtenga el objeto InputStream a través del objeto Socket obtenido anteriormente, e instale el archivo IO para leer los datos. Aquí imprimimos el contenido.
public class ServerClient {public static void main (string [] args) {int port = 8919; intente {ServerSocket Server = new Serversocket (puerto); Socket socket = server.accept (); Lector lector = new InputStreamReader (Socket.getInputStream ()); char chars [] = nuevo char [1024]; int len; StringBuilder Builder = new StringBuilder (); while ((len = lector.read (chars))! = -1) {builder.append (new String (chars, 0, len)); } System.out.println ("Recibir del mensaje del cliente =:" + Builder); lector.close (); socket.close (); servidor.close (); } catch (Exception e) {E.PrintStackTrace (); }}}Cerrar el objeto IO
No se puede olvidar. Finalmente, necesito cerrar el objeto IO correctamente para garantizar la liberación correcta de recursos.
Tenga en cuenta un ejemplo
Aquí agregamos un ejemplo, utilizando Socket para implementar un servidor Echo, es decir, el servidor pasará los datos enviados por el cliente al cliente. El código es muy simple.
import java.io.*; import java.net.*; public class EchoServer {public static void main (string args []) {// sección de declaración: // declara un socket de servidor y un socket de cliente para el servidor // declarar una entrada y un flujo de salida Serversocket EchoServer = null; Línea de cadena; DataInputStream es; PrintStream OS; Socket clientsocket = null; // Intenta abrir un socket de servidor en el puerto 9999 // Tenga en cuenta que no podemos elegir un puerto inferior a 1023 si no somos // usuarios privilegiados (root) intente {echoserver = new ServerSocket (9999); } catch (ioException e) {System.out.println (e); } // Crea un objeto Socket desde el SerververSocket para escuchar y aceptar // Conexiones. // Abrir transmisiones de entrada y salida prueba {clientsocket = echoserver.accept (); es = nuevo DataInputStream (Clientsocket.GetInputStream ()); OS = new PrintStream (Clientsocket.getOutputStream ()); // Mientras recibamos datos, haga eco de esos datos al cliente. while (true) {line = is.readline (); OS.println (línea); }} catch (ioException e) {System.out.println (e); }}}Compile y ejecute el código anterior y realice la siguiente solicitud, puede ver el contenido de los datos llevados por la solicitud del cliente.
15:00 $ curl http://127.0.0.1:9999/?111get/? 111 http/1.1user-agent: curl/7.37.1host: 127.0.0.1:99999accept: */ *
Resumir
Es bastante interesante realizar la programación de cliente cliente, y la programación de socket en Java es más fácil y más rápida que otros idiomas (como C).
El paquete Java.net contiene muchas clases potentes y flexibles para que los desarrolladores se programen redes. Al programar redes, se recomienda usar la API debajo de este paquete. Al mismo tiempo, el paquete Sun.* también contiene muchas clases relacionadas con la programación de redes, pero no se recomienda usar la API debajo de este paquete, porque este paquete puede cambiar. Además, no se puede garantizar que este paquete se incluya en todas las plataformas.
Lo anterior es una compilación de la información del socket Java. Continuaremos agregando conocimiento relevante en el futuro. ¡Gracias por su apoyo para este sitio web!