Mostrando entradas con la etiqueta Sockets. Mostrar todas las entradas
Mostrando entradas con la etiqueta Sockets. Mostrar todas las entradas

viernes, 21 de julio de 2017

C# Networking Basics: Sockets

Socket is the name given to an abstraction through which an application may send and receive data. The term “Socket” refers to the Berkeley Sockets Interface, which was developed in 1978 for network programming with UNIX and was popularized by C programmers.

Because of the popularity of that abstraction, this term has been reused in many programming model including .NET technology. The main types of sockets in TCP/IP today are: stream sockets and datagram sockets, both use TCP as the end-to-end protocol with IP underneath, the .NET framework provides a clear distinction between using TCP and UDP, defining a separate set of classes for both protocols.

Stream Sockets

Socket based communications in C# employ stream sockets, when processes communicate over a network .NET Framework technology uses the streams model to establish a connection between two o more processes. With stream sockets, a process (running program) establishes a connection to another process.

A socket can hold two streams: one input stream and one output stream when the sender sends data to another process through the network by writing to the output stream associated with the socket, the receiver reads data written by the sender by reading from the input stream associated with the socket. While the connection is in place, data flows between the processes in continuous stream.

Addressing the connection

When you make a network connection, you need to know the address or the name of the remote machine, IPv4 uses 32 bit binary addresses to identify communicating hosts a client must specify the IP address of the host running the server program when it initiates the communication. In addition, a network connection requires a port number, after you connect to the proper host, you must identify a particular purpose for the connection. So, you can use a particular port number to communicate with the specific program.

Port Numbers

In TCP/IP port numbers are 16-bit numbers and the values range from 0-65535. In practice, port numbers below 1024 are reserved for predefined services, and you should not use them unless communicating with one of those services, client port numbers are allocated by the operating system to something not in use, while server port numbers are specified by the programmer, and are used to identify a particular service. Both client and server must agree in advance on which port to use. If the port numbers used by the two parts of the system do not agree, communication does not occur. Ports are divided into the following ranges:

  • 0-1023: well-known ports
  • 1024-49151: registered ports
  • 49152-65535: dynamic or private ports

Minimal TCP/IP Server

The System.Net.Sockets.TcpListener class is used to create server applications. TcpListener provides a simple wrapper around the socket classes, here is a simple TCP Server that accepts a single client connection.

Example 1: Implementing a network streaming server

To compile this program using mono, type the following command at your command prompt:
$ mcs /t:exe -out:SimpleTCPServer.exe SimpleTCPServer.cs
And to run it, type this command line:
$mono SimpleTCPServer.exe
And you’ll see the following output on your screen:

Fig 1: Result of running the SimpleTCPServer program.

Minimal TCP/IP Client

The client is a simple console application, this application uses the TcpClient class to connect to the running server, and receives the returned message.

Example 2: Implementing a client

To compile this program using mono, type the following command at your command prompt:
mcs /t:exe -out:SimpleTCPClient.exe SimpleTCPClient.cs
And to run it, type this command line:
$mono SimpleTCPClient.exe
And you’ll see the following output on your screen:

Fig 2: Result of running the SimpleTCPClient program.

sábado, 12 de noviembre de 2016

Entendiendo la programación de Sockets UDP con GTK# y .NET

UDP (User Datagram Protocol) es un protocolo de datagramas, no orientado a la conexión mucho más sencillo, poco fiable y de alto rendimiento, que a diferencia de TCP no incluye todas características para garantizar la entrega de paquetes, tales como recuperación de fallas, chequeo de errores o control de flujo. Debido a estas características UDP debe utilizarse en casos específicos, donde se asuma que el rendimiento es mejor que la fiabilidad:

  1. Cuando se transmite una pequeña cantidad de datos en periodos muy cortos de tiempo.
  2. Aplicaciones de “consulta y respuesta”, que trasmiten una consulta y esperan una respuesta inmediata.
  3. En sistemas de compresión para la transmisión de audio y video que pueden aceptar cierta cantidad de corrupción o perdida de paquetes.
  4. Algunas aplicaciones tienen su propio mecanismo de entrega de transporte, así que no necesitan de una capa de transporte. Estas aplicaciones usaran UDP mas eficientemente que TCP.

Por su rendimiento, UDP es recomendable en aplicaciones en donde es aceptable que algunos paquetes se pierdan durante la comunicación, como video streaming de video o algún protocolo multicasting como DNS.

La cabecera UDP tiene solo 4 campos: puerto origen, puerto destino, longitud y checksum. Los campos origen y destino tiene la misma funcionalidad que se tienen en la cabecera TCP. La longitud del campo especifica la longitud de la cabecera UDP y el campo checksum permite la revisar integridad del paquete.

Fig 1 Los campos del paquete UDP.

La clase UDPClient

La clase UdpClient es responsable de manejar mensajes punto a punto (point-to-point) y multicasting con el protocolo UDP; la clase UdpClient utiliza endpoints, esta clase puede ser construida inicialmente con el parámetro de un host o bien este parámetro puede especificarse durante el método Send().

Tambien proporciona un método Receive() que bloquea el hilo de ejecución hasta que un datagrama es recibido.

La clase UdpClient es una pequeña interfaz comparado a la clase TcpClient. Esto refleja la simple naturaleza de este protocolo en comparación con TCP. Mientras que ambas clases TcpClient y UdpClient utilizan un Socket internamente, la clase UdpClient no contiene un método para regresar un flujo de red (stream) para escribir y leer, en lugar de eso tiene un método Send() que acepta un arreglo de bytes como parámetro, mientras el método Receive() recibe un arreglo de bytes.

Fig 2 Miembros esenciales de la clase UDP Client.

Metodo o propiedad Descripción
Receive Recibe un datagrama UDP que fue enviado por una máquina remota.
Send Envia un datagrama UDP a una máquina remota.
Client Obtiene el socket subyacente que utiliza la clase.

Ejemplo de una comunicación entre un clientes y un servidor UDP

Es importante entender que en un modelo de comunicación sin conexión como UDP la comunicación se limita estrictamente a un modelo de petición/respuesta, que se lleva de la siguiente manera:

Fig 3 Modelo de comunicación petición/respuesta

Cada petición es un arreglo de bytes se salida procedente del cliente. Este arreglo de bytes se envía al servidor mediante TCP/IP, donde se convierte en la entrada del servidor. La respuesta entonces es el arreglo de bytes que salen del servidor para actuar como la entrada del cliente. Debido a la simpleza de este modelo, presenta las siguientes limitaciones:

  • Falta de conexión continua
  • Falta de fiabilidad
  • Seguridad insuficiente

Para mostrar como trabaja la comunicación entre un cliente y un servidor UDP utilizando la clase UdpClient escribí dos programas: un servidor y un cliente UDP. Ambos programas utilizan una interfaz de usuario (GUI) en GTK# para comunicarse entre ellos.

Fig 4 Ejemplo de un time server UDP con una GUI GTK#

Fig 5 Ejemplo de un cliente UDP con una GUI GTK#

Pasos para la construcción de un servidor UDP GTK#

El servidor UDP envía la fecha y la hora actual de la máquina a los clientes que se conecten en su número de puerto, durante los minutos que el servidor se encuentre activo, ambos el número de puerto y los minutos son especificados por el usuario en la pantalla.

El proyecto del servidor se compone de dos clases:

  1. La clase MainWindowServer.cs es la clase que construye la GUI del programa, obtiene los parámetros: número de puerto y minutos de ejecución del subproceso servidor, informa acerca de su estado o las posibles excepciones.
  2. La clase Program.cs es la clase principal que donde se ejecuta el servidor.

Para construir un servidor UDP se requieren de los siguientes pasos:

1) Crear una objeto UdpClient que al construirse sin argumentos se le asigna un número de puerto de la IP local.

    UdpClient udpClient = new UdpClient();

2) Construir un objeto IPEndpoint asociando una IP para este ejemplo utilice la dirección local y el número de puerto donde se conectara para enviar la respuesta (response) del servidor.

    IPEndPoint IPremoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"),serverPort);

3) Utilizar la clase Encoding para convertir el texto de la respuesta en un arreglo de bytes UTF8, y enviarla por la red con el método Send().

    byte[] data = Encoding.UTF8.GetBytes(response.ToString());
    udpClient.Send(data,data.Length,IPremoteEP);

Pasos para la construcción de un cliente UDP GTK#

El cliente UDP solicita un petición al número de puerto del servidor, recibiendo la respuesta como una matriz de bytes, la convierte a una cadena y la muestra en la pantalla.

El proyecto del cliente UDP GTK# se compone de 2 clientes:

  1. 1. La clase MainWindow.cs es la clase que construye la GUI del cliente, solicita los parámetros: numero de puerto y dirección IP para configurar la comunicación, maneja los eventos para recibir la respuesta del servidor y mostrar el resultado en pantalla o las posibles excepciones.
  2. 2. La clase Program.cs es la clase principal donde se ejecuta el cliente

Para construir un cliente UDP se requieren de los siguientes pasos:

1) Se crea un objeto UdpClient y se le especifica como parámetro el número de puerto al cual se enlazará.

    UdpClient client = new UdpClient(portToReceive);

2) Se crea el IPEndPoint para recibir la matriz de bytes con los parámetros IPAddress.Any (Indica que el servidor debe escuchar por clientes en todas las interfaces de red) y el número de puerto cero (para solicitar números de puertos dinámicos).

    IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);

3) Se obtiene el arreglo de bytes del IPEndPoint

    byte[] data = client.Receive(ref anyIP);

4) Se convierte el arreglo de bytes a una cadena

    text = Encoding.UTF8.GetString(data);

5) Una vez obtenido el mensaje se debe cerrar el Socket

    client.Close();

A continuación unas imágenes del cliente y del servidor comunicándose entre si.

Fig 6 Configurando el servidor de fecha y hora

Fig 7 Ejecutando el servidor de fecha y hora

Fig 8 Ejecutando el cliente GTK# Udp

Fig 9 Obteniendo la respuesta de servidor UDP

viernes, 9 de septiembre de 2016

Entendiendo la programación de Sockets con GTK# y .NET

¿Qué son los sockets?

Los Sockets o mejor dicho los Berkeley Sockets (BSD IPC) son la combinación exclusiva de una dirección IP y un numero de puerto TCP que habilita a los servicios (procesos en ejecución) de una computadora el poder intercambiar datos a través de la red. Los servicios de red utilizan los sockets para comunicarse entre los equipos remotos. Por ejemplo el siguiente comando:

        $ telnet 192.168.1.14 80
      

Este comando solicita una conexión desde un puerto aleatorio en el cliente (por ejemplo: 5643) al puerto 80 en el servidor (que es el puerto asignado para el servicio HTTP). Con la siguiente figura (fig 1) se ilustra a detalle este esquema denominado cliente-servidor.

Fig 1 Una comunicación utilizando números de puerto para transmitir datos.

Históricamente los sockets son una API (Application Programming Interface) de programación estándar utilizada para construir aplicaciones de red que vienen desde el sistema UNIX BSD. Esta interface de programación para la capa 4 del modelo OSI (OSI Model Layer 4) permite a un programador tratar una conexión de red como un flujo de bytes que puede escribirse o leerse sin demasiada complejidad. Con un socket se pueden realizar siete operaciones básicas:

  1. Conectarse a una máquina remota.
  2. Enviar datos.
  3. Recibir datos.
  4. Cerrar una conexión.
  5. Escuchar para los datos entrantes.
  6. Aceptar conexiones desde maquinas remotas en el puerto enlazado.
  7. Enlazarse a un puerto.

Los Sockets pueden ser orientados a la conexión (Stream Socket) o no (Message-based Socket).

Los Stream Sockets son ideales para transmitir grandes volúmenes de información de manera confiable. Una conexión Stream Socket se establece mediante el mecanismo three-hand shake de TCP, los datos se transmiten y cada paquete se revisa para asegurarse de la exactitud en la transmisión.

Los Datagram Sockets son apropiados para transferencias de datos cortas, rápidas y sin necesidad de un chequeo de errores. Los desarrolladores de aplicaciones los prefieren por ser rápidos y muy fáciles de programar.

Fig 2 Tipos de Socket

El Framework .NET posee las clases de alto y bajo nivel que encapsulan la funcionalidad de un Socket (tanto TCP como UDP) para construir aplicaciones de red con relativa facilidad y sin preocuparse por todo el intricado mecanismo de comunicación que necesitaría muchas líneas de código. La siguiente lista describe las clases principales:

  • NetworkStream: Una clase derivada de la clase Stream representa el flujo de datos de entrada o de salida desde la red.
  • TcpClient: Crea conexiones TCP de red para conectarse a un socket de servidor.
  • TcpListener: Se utiliza para escuchar peticiones de red TCP.
  • UdpClient: Crea conexiones UDP de red con posibilidad de multicasting.
  • Socket: Es una clase de bajo nivel que envuelve a la implementación winsock, las clases TcpClient, TcpListener y UDPClient utilizan esta clase para sus operaciones, se puede afirmar que la clase Socket tiene las operaciones de estas clases más otras funcionalidades mucho más avanzadas y de más bajo nivel.

Pasos para la construcción de un Servidor TCP GTK#

Un servidor TCP siempre está ejecutándose de forma continua hasta que recibe una solicitud de conexión por parte de un cliente, cuando se recibe esta solicitud, el servidor establece una conexión con el cliente y utiliza dicha conexión para el intercambio de datos. Si los programas se comunican a través de TCP los datos que se procesan se envían y se reciben como flujo de bytes.

Para demostrar estos conceptos escribí dos programas: el de un servidor y el de un cliente TCP. Ambos utilizan una interfaz de usuario (GUI) en GTK# para comunicarse entre ellos mediante mensajes de texto.

Fig 3 Ejemplo de un servidor TCP con una GUI GTK#.

Fig 4 Ejemplo de un cliente TCP con una GUI GTK#.

Pasos para la construcción de un Servidor TCP GTK#

El proyecto del servidor TCP GTK# se compone de 2 clases:

  1. La clase MainWindowServer.cs es la clase que construye la GUI del programa, maneja los eventos para enviar los mensajes al cliente y las excepciones o mensajes que el programa notifique.
  2. La clase Program.cs es la clase principal que donde se ejecuta el servidor.
Para construir el servidor TCP se requieren de los siguientes pasos:

1) Crear un objeto IPEndpoint que asocia una dirección IP y un número de puerto.

IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any,6000);

2) Crear un objeto TcpListener que reciba como argumento un objeto IPEndpoint. (Aquí el objeto TcpListener oculta la intricada programación de un Server Socket para una facilidad en la programación)

listener = new System.Net.Sockets.TcpListener(ipEndPoint); 

3) Iniciar el objeto TcpListener para que escuche las peticiones.

listener.Start();

4) Se utilizar un ciclo para que el Server Socket escuche o espere indefinidamente hasta recibir una petición, cuando el servidor recibe la petición crea una conexión hacia el cliente y regresa un objeto Socket del ensamblado System.Net.Sockets.Socket.

connection = listener.AcceptSocket();

5) Se obtiene el flujo de comunicación del Socket.

System.Net.Sockets.NetworkStream socketStream = 
new System.Net.Sockets.NetworkStream(connection);

6) Finalmente se asocia el flujo de comunicación del Server Socket con un escritor y un lector binario para transferir y recibir datos a través del flujo de comunicación.

using(writer = new BinaryWriter(socketStream))
{
using(BinaryReader reader = new BinaryReader(socketStream))
{
//the stream goes here 
}
}

Es muy importante que una vez que se finaliza la comunicación con el cliente cerrar el flujo y la conexión mediante con el método Close de cada uno de los objetos.

socketStream.Close();
connection.Close(); 

Pasos para la construcción de un cliente TCP GTK#

El proyecto del cliente TCP GTK# se compone de 2 clases:

  1. La clase MainWindow.cs es la clase que construye la GUI del cliente, maneja los eventos para recibir y enviar los mensajes al servidor, y mostrar las excepciones o mensajes que ocurran.
  2. La clase Program.cs es la clase principal del cliente

Para construir el cliente TCP se requieren de los siguientes pasos, algunos son idénticos a los que se escribieron para el servidor:

1) Crear un objeto IPEndpoint que asocia la dirección IP y el número de puerto del servidor, generalmente estos datos son fijos ya que los servidores se configuran para tenerlos de manera estática. (en este ejemplo utilice una sola máquina como servidor y como cliente)

  IPEndPoint localEndPoint = 
  new IPEndPoint(IPAddress.Loopback,6000);
  

2) Se crea un Socket de cliente y se conecta al puerto del servidor.

  client.Connect(localEndPoint);
  

3) Se obtiene el flujo de comunicación del Socket

  output = client.GetStream();
  

4) Se crean los objetos lector y escritor para trabajar con el flujo de comunicación.

   using(writer = new BinaryWriter(output))
   {
    using(reader = new BinaryReader(output))
    {
//the stream goes here 
    }
  }
  

Finalmente cuando se termina la comunicación con el servidor, se cierra el flujo de datos y la conexión con el método Close de cada objeto.

    output.Close();
    client.Close();
  

La clase TcpFlags

Ambos proyectos utilizan la clase TcpFlags, la cual pretende ilustrar básicamente como son las banderas TCP (aquí más detalles de las TCP Flags) que utiliza la capa de transporte (layer 4) para manejar la comunicación entre dos máquinas.

A continuación unas imágenes del cliente y servidor comunicándose entre si.
Fig 5 Enviando un mensaje desde el cliente al servidor.

Fig 6 Recibiendo el mensaje del cliente.

Fig 7 Enviándole un mensaje al cliente desde el servidor.

Fig 8 Desconectándose del servidor.

martes, 2 de agosto de 2016

Entendiendo TCP Control Flags (los bits de control TCP)

El protocolo TCP (Transport Control Protocol) proporciona la comunicación orientada a la conexión entre dos sistemas utilizando características tales como: Three-way handshake, reconocimientos, y números de secuencia. Adicionalmente a esas características TCP tiene 6 banderas de control (control flags) o bits de bandera que se usan para dominar la funcionalidad de las conexiones, los 6 bits que son utilizados durante el ciclo de la conexión son: Urgent (URG), Acknowledgment (ACK), Push (PSH), Reset (RST), Synchronize (SYN) y Finish (FIN).

La posición de cada uno de los bits es una bandera para indicar si una funcionalidad TCP está habilitada o deshabilitada, poniendo el valor del bit en 1 es ON, si es 0 significa OFF.

A continuación la descripción de cada uno de los bits por su correspondiente posición:

Urgent (URG): Se utiliza para notificarle a un sistema que el paquete tiene datos urgentes dentro del campo TCP que reconocen una actividad urgente o con prioridad, por ejemplo cuando un usuario presiona la combinación CTRL-BREAK, el resultado de este bit le indica a TCP que estos datos deben tomar precedencia sobre la transmisión de datos y enviarse inmediatamente.

Acknowledgment (ACK): El bit de reconocimiento se utiliza por uno de los sistemas para indicar el reconocimiento de un paquete TCP de otro sistema. Esto indica que hay un numero de reconocimiento en el campo de reconocimiento que se envía como respuesta a un petición SYNC.

Push (PSH): Este informa a TCP de entregar los datos inmediatamente hacia la capa superior sin almacenarlos en el buffer.

Reset (RST): Indica que una conexión TCP debe reiniciar la conexión, quizás debido a un error.

Synchronize (SYN): El bit de sincronización se utiliza para solicitar la conexión TCP con otro sistema. Una solicitud de conexión tiene SYN = 1 y ACK = 0.

Finish (FIN): Este bit se utiliza para terminar la conexión en un sistema, indica que el emisor no tiene más datos que enviar. La desconexión es simétrica.

Fig 1 TCP Header (la cabecera TCP).

Flags (UAPRSF)
  • U (1 = Urgent pointer valid)
  • A (1 = Acknowledgement field value valid)
  • P (1 = Push data)
  • R (1 = Reset connection)
  • S (1 = Synchronize sequence numbers)
  • F (1 = no more data; Finish connection)