Está en la página 1de 22

CARRERA DE COMPUTACION

SEMESTRE SEXTO

PERÍODO SEP/2016 - MAR/2017

PROGRAMACIÓN DE SISTEMAS OPERATIVOS

TEMA:
CREACION DE UNA APLICACIÓN DE CHAT LAN

AUTORES:
RICARDO A. ALVARADO MORALES
RAFAEL I. COBEÑA LOOR
SERVIO G. PACHARD VELEZ
FACILITADOR:
ING. MARLON NAVIA
CALCETA, OCTUBRE/ 2016

INTRODUCCION
Una red es un conjunto de computadores, equipos de comunicaciones y otros
dispositivos que se pueden comunicar entre sí por medio de cables, señales,
ondas o cualquier otro método de transporte de datos, que comparten
información, recursos, servicios, etc.
Hoy en día las redes de computadoras son de suma importancia en nuestra
vida, ya sea en el ámbito laboral, estudiantil, social, etc. y así se podría seguir
mencionando una enorme cantidad de áreas en las que las redes de
computadoras están involucradas.
Las redes tienen modelos las cuales tienen protocolos de red que permiten la
comunicación entre dispositivos, entre ellos tenemos el modelo TCP/IP y el
modelo OSI las cuales se dividen en varias capas que cumplen funciones
específicas.
Entre las capas de aplicación e internet del modelo TCP/IP se encuentra la
capa de transporte, una pieza fundamental de la arquitectura de red en capas.
Esta capa desempeña el papel crítico de proporcionar directamente servicios
de comunicación a los procesos de aplicación mediante protocolos como UDP,
TCP, SCTP entre otros.
El presente trabajo se enfoca en la realización de una aplicación de chat, en la
cual se pueda difundir mensajes mediante el protocolo UDP de la capa de
transporte del modelo TCP/IP, utilizando el puerto 5757
Para el desarrollo de esta aplicación se utilizó el entorno de desarrollo Visual
Basic en el lenguaje C#

OBJETIVOS ESPESIFICOS  Investigar acerca de la habilitación de los puertos TCP y UDP para transporte de paquetes. .OBJETIVOS OBJETIVO GENERAL Emplear protocolos de nivel de Transporte (TCP y UDP) para programas del nivel de Aplicación. de acuerdo a características y necesidades de los mismos.  Crear una aplicación de chat LAN en la cual se utilice los puertos de transporte investigados  Verificar el correcto funcionamiento del aplicativo de Chat.

el software TCP/IP está organizado en cuatro capas conceptuales que se construyen sobre una quinta capa de hardware. El TCP / IP es la base del Internet que sirve para enlazar computadoras que utilizan diferentes sistemas operativos. incluyendo PC. MODELO TCP/IP El modelo TCP/IP es una serie de normas que detallan como deben comunicarse los ordenadores y el modo de interconectar las redes para permitir que diferentes sistemas puedan cooperar compartiendo sus recursos. Fue desarrollado por una comunidad de investigadores de una agencia gubernamental norteamericana: ARPA (Advanced Research Projects Agency) bajo petición del Departamento de Defensa Norteamericana con objeto de que los sistemas multifabricante de Defensa pudieran dialogar entre sí y se implementó por primera vez en Diciembre del 69 denominándose ARPAnet. ejecutándolo en el ARPANET una red de área extensa del departamento de defensa. TCP / IP fue desarrollado y demostrado por primera vez en 1972 por el departamento de defensa de los Estados Unidos. APLICACION TRANSPORTE . minicomputadoras y computadoras centrales sobre redes de área local y área extensa.1. el Transmission Control Protocol (TCP) y el Internet Protocol (IP). El siguiente esquema muestra las capas conceptuales así como la forma en que los datos pasan entre ellas. MODELO DE CAPAS En términos generales. MARCO TEÓRICO 1.2.CAPITULO I. Todos juntos llegan a ser más de 100 protocolos diferentes definidos en este conjunto. 1. El nombre TCP / IP Proviene de dos protocolos importantes de la familia.

PROTOCOLO UDP Es un protocolo no orientado a conexión de la capa de transporte del modelo TCP/IP. con una dirección de destino. Este tipo de comunicación se conoce frecuentemente como comunicación punto a punto. Este protocolo es muy simple ya que no proporciona detección de errores (no es un protocolo orientado a conexión). Puede también proporcionar un transporte confiable. El software de transporte divide el flujo de datos que se está enviando en pequeños fragmentos (por lo general conocidos como paquetes) y pasa cada paquete. Para hacer esto. La capa de transporte debe aceptar datos desde varios programas de usuario y enviarlos a la capa del siguiente nivel. el software de protocolo de transporte tiene el lado de recepción enviando acuses de recibo de retorno y la parte de envío retransmitiendo los paquetes perdidos.1. hacia la siguiente capa de transmisión. CAPA DE TRANSPORTE La principal tarea de la capa de transporte es proporcionar la comunicación entre un programa de aplicación y otro. asegurando que los datos lleguen sin errores y en secuencia.INTERNET INTERFAZ DE RED HARDWARE 1. 1. La capa de transporte regula el flujo de información. Aun cuando en el esquema anterior se utiliza un solo bloque para representar la capa de aplicación. En esta capa se encuentran los protocolos UDP y TCP.3. una computadora de propósito general puede tener varios programas de aplicación ingresando la red de redes al mismo tiempo. .3.

este campo es opcional. 1. En el nivel de aplicación. los 16 bits de este campo se pondrán en cero. el protocolo IP). con el encabezado incluido. en particular para mensajes unidireccionales). Significado de los diferentes campos  Puerto de origen: es el número de puerto relacionado con la aplicación del remitente del segmento UDP. Datos (longitud variable). o van hacia él. Por lo tanto. el encabezado tiene una longitud de 4 x 16 bits (que es 8 x 8 bits). Este campo representa una dirección de respuesta para el destinatario. Esto significa que si el puerto de origen no está especificado. Por lo tanto. En este caso. aunque se puedan perder algunos paquetes. el encabezado del segmento UDP es muy simple: puerto de origen (16 bits).UDP se usa cuando se buscan transmisiones con una cantidad de información baja en los paquetes y altas velocidades de transferencia. posibilita la administración de datos que vienen del nivel más bajo del modelo. Sin embargo.3.  Longitud: este campo especifica la longitud total del segmento. suma de comprobación del encabezado (16 bits). PROTOCOLO TCP Es uno de los principales protocolos de la capa de transporte del modelo TCP/IP. . longitud total (16 bits). el destinatario no podrá responder (lo cual no es estrictamente necesario.2.  Puerto de destino: este campo contiene el puerto correspondiente a la aplicación del equipo receptor al que se envía.  Suma de comprobación: es una suma de comprobación realizada de manera tal que permita controlar la integridad del segmento. (es decir. puerto de destino (16 bits). por lo tanto la longitud del campo es necesariamente superior o igual a 8 bytes.

aplicaciones) en la misma línea  pueda circular simultáneamente. que no se pierda información. . TCP se usa cuando se requiere trasmisión de datos con mucha confiabilidad. es decir. Las principales características del protocolo TCP son las siguientes:  TCP permite colocar los datagramas nuevamente en orden cuando  vienen del protocolo IP. TCP permite multiplexar los datos. TCP es un protocolo orientado a conexión. que la información que viene de diferentes fuentes (por ejemplo. TCP permite que los datos se formen en segmentos de longitud variada  para "entregarlos" al protocolo IP. TCP permite que el monitoreo del flujo de los datos y así evitar la  saturación de la red. fijando el campo del protocolo en 6 (para que sepa con anticipación que el protocolo es TCP).Cuando se proporcionan los datos al protocolo IP. es decir. los agrupa en datagramas IP. que permite que dos máquinas que están comunicadas controlen el estado de la transmisión. es decir.

Sockets.Forms.ComponentModel. // Nombre con el que el usuario ha iniciado sesión en la sala de chat } // La colección de todos los clientes conectados en el ambiente (una matriz de tipo ClientInfo) ArrayList clientList.Windows. System.Text. List. // Salir del servidor Message. // socket de la red en el que el servidor escucha a los clientes .Net. // Socket del cliente public string strName.Data. System. System. namespace Server { // comandos para la interacción entre el servidor y el cliente enum Command { Login. System.Collections.Drawing. System.Collections.DESARROLLO DELA APLICACIÓN CÓDIGO FUENTE DEL PROYECTO SERVIDOR using using using using using using using using using using System. System. // Enviar un mensaje de texto a todos los clientes de chat // Obtener una lista de usuarios en la sala de chat del servidor Null // sin comando } public partial class SGSserverForm : Form { // La estructura ClientInfo contiene la información necesaria acerca de cada //cliente conectado al servidor struct ClientInfo { public EndPoint endpoint. System. System. // Registrar en el servidor Logout.Generic.Net. System.

MessageBoxIcon. ref epSender).Message. } catch (Exception ex) { MessageBox. byte[] byteData = new byte[1024]. SocketType. // El epSender identifica los clientes entrantes EndPoint epSender = (EndPoint) ipeSender.None. ProtocolType.Any.Any.Dgram. } } private void OnReceive(IAsyncResult ar) { try { IPEndPoint ipeSender = new IPEndPoint(IPAddress.BeginReceiveFrom (byteData. // Transformar la matriz de bytes recibidos desde el usuario en una // forma inteligente de los objetos de datos Data msgReceived = new Data(byteData).Show(ex. public SGSserverForm() { clientList = new ArrayList(). InitializeComponent().Any. ref epSender.Error). } private void Form1_Load(object sender. IPEndPoint ipeSender = new IPEndPoint(IPAddress. 0). .OK. new AsyncCallback(OnReceive). // Empezar a recibir datos serverSocket. SocketFlags. 1000). // dirección para el servidor serverSocket.Length.EndReceiveFrom (ar.Bind(ipEndPoint). // Estamos utilizando sockets UDP serverSocket = new Socket(AddressFamily. serverSocket. "SGSServerUDP". EventArgs e) { try { CheckForIllegalCrossThreadCalls = false. MessageBoxButtons.Udp).InterNetwork.Socket serverSocket. 0). 0. // Asignar el cualquier IP de la máquina y escuchar en el puerto número 1000 IPEndPoint ipEndPoint = new IPEndPoint(IPAddress. byteData. EndPoint epSender = (EndPoint)ipeSender. epSender).

// Vamos a enviar este objeto en respuesta solicitan los usuarios Data msgToSend = new Data(). clientInfo.Logout: // Cuando un usuario desea cerrar sesión en el servidor entonces // en la lista de clientes se cerrará la conexión correspondiente int nIndex = 0. case Command.Add(clientInfo).Message: // Establecer el texto del mensaje que vamos a transmitir a todos los usuarios msgToSend.strMessage = msgReceived.strName = msgReceived. switch (msgReceived.strMessage = "<<<" + msgReceived.strName + " se ha unido a la habitación>>>".Login: // Cuando un usuario se conecta al servidor.cmdCommand. } ++nIndex.strMessage.RemoveAt(nIndex).strMessage = "<<<" + msgReceived. entonces ella se suman a nuestra //lista de clientes ClientInfo clientInfo = new ClientInfo(). clientList.strName + ": " + msgReceived.strName. foreach (ClientInfo client in clientList) { if (client. break. cuando envíe a los demás el tipo del mensaje sigue siendo el mismo msgToSend.strName + " ha salido de la habitación>>>". case Command. clientInfo. .endpoint = epSender.cmdCommand = msgReceived. msgToSend.strName. } msgToSend. byte [] message. o un mensaje de texto simple // Luego. desconexión. // Establecer el texto del mensaje que vamos a transmitir a todos los usuarios msgToSend. break.endpoint == epSender) { clientList.cmdCommand) { case Command. break. // Si el mensaje es de conexión.strName = msgReceived. break.

strName = null.cmdCommand != Command.Length.Logout) { // Empezar a escuchar el mensaje a enviar por el usuario serverSocket. message.strMessage + "\r\n". epSender. 0. msgToSend.None.Login) { //enviar mensaje a todos los usuarios serverSocket.endpoint != epSender || msgToSend.strName + "*". 0.endpoint).ToByte().List: // Enviar los nombres de todos los usuarios en la sala de chat para el nuevo usuario msgToSend. clientInfo. new AsyncCallback(OnSend).None. break. // Recoge los nombres de usuario en la sala de chat foreach (ClientInfo client in clientList) { // Para simplificar las cosas que usamos asterisco como el marcador para separar los nombres de usuario } msgToSend.endpoint.strMessage = null.List) // mensajes de la lista no se emiten { message = msgToSend.case Command. epSender).cmdCommand != Command. // Enviar el nombre de los usuarios en la sala de chat serverSocket. message = msgToSend. new AsyncCallback(OnReceive).cmdCommand != Command. ref epSender.ToByte(). msgToSend. } . } if (msgToSend. byteData. new AsyncCallback(OnSend). SocketFlags. SocketFlags.BeginSendTo (message. SocketFlags. 0. foreach (ClientInfo clientInfo in clientList) { if (clientInfo.List.Text += msgToSend. } } txtLog.strMessage += client. clientInfo.cmdCommand = Command. } // Si el usuario se está conectando a cabo. entonces no necesitamos escuchar de ella if (msgReceived.BeginReceiveFrom (byteData.Length.None. message.BeginSendTo (message. epSender).Length.

EndSend(ar).cmdCommand = (Command)BitConverter. 8). "SGSServerUDP". // Las cuatro siguientes almacenan la longitud del mensaje int msgLen = BitConverter. EventArgs e) { } } // La estructura de datos por el cual el servidor y el cliente interactúan con el otro class Data { //constructor por defecto public Data() { this.Error). } // Convierte los bytes en un objeto de tipo de datos public Data(byte[] data) { // Los primeros cuatro bytes son para el Comando this. MessageBoxButtons.strMessage = null. 0). MessageBoxIcon. // Las cuatro siguientes almacenan la longitud del nombre int nameLen = BitConverter.Show(ex.ToInt32(data.Message. MessageBoxButtons.Message. this.strName = null. MessageBoxIcon.ToInt32(data. } } public void OnSend(IAsyncResult ar) { try { serverSocket. "ServerUDP". } } private void txtLog_TextChanged(object sender.cmdCommand = Command. this. } catch (Exception ex) { MessageBox.} catch (Exception ex) { MessageBox.OK. 4).ToInt32(data.Null. // Esta comprobación se asegura de que Nombre ha sido aprobada en la matriz de .Show(ex.Error).OK.

strName = Encoding.Length)).GetBytes(strName)).GetBytes((int)cmdCommand)).UTF8. msgLen). etc. // Esto comprueba si hay un campo de mensaje nula } if (msgLen > 0) this.GetBytes(strName.bytes if (nameLen > 0) this.GetBytes(0)).GetString(data. enviar mensajes.strMessage = null.AddRange(BitConverter.) } } .AddRange(Encoding. desconexión. } return result.AddRange(BitConverter. // Añadir la longitud del nombre if (strName != null) result. 12. public string strName. //mensaje de texto public Command cmdCommand.ToArray(). //longitud del mensaje if (strMessage != null) result.strName = null.Length)).strMessage = Encoding.GetString(data. else this. // Cuatro primeros son para el Comando result.AddRange(BitConverter. 12 + nameLen. por último añadimos el texto del mensaje a nuestra matriz de bytes if (strMessage != null) result.AddRange(BitConverter.UTF8.GetBytes(0)).GetBytes(strMessage. // Y.UTF8.AddRange(BitConverter.UTF8. else result. // Convierte la estructura de datos en una matriz de bytes public byte[] ToByte() { List<byte> result = new List<byte>(). //agregar nombre if (strName != null) result. else this. nameLen). else result. // Nombre con el que el cliente se registra en la habitación public string strMessage.GetBytes(strMessage)). // tipo de comando (conexión.AddRange(Encoding.

Figura 1.CAPTURA DE PANTALLA DEL SERVIDOR La ventana del servidor nos mostrara todos los mensajes que se transmitido durante el tiempo que ha estado activo. este servidor poder ser accedido por los demás host remotos (clientes) mediante la ip de la máquina que esté corriendo el servidor. Ventana del servidor cuando se ejecuta y no hay clientes conectados .

mensaje_a_enviar. System. System.strName = Nombre. System.Text = null.strMessage = txtMessage.Data.Collections. } //Funcion para enviar el mensaje a las personas conectadas.Net. System.ToByte(). null). mensaje_a_enviar. mensaje_a_enviar. //Obtener una lista de usuarios en la sala de chat del servidor Null } public partial class clase_Cliente : Form { public Socket clienteSocket. txtMessage. System. //Punto final del servidor byte []byteData = new byte[1024].Net. public clase_Cliente() { InitializeComponent(). //Enviar un mensaje de texto a todos los clientes de chat List. new AsyncCallback(OnSend). System. 0. byteData.Forms.Figura 2.Text.Sockets. System.Mensaje.Windows. EventArgs e) { try { //asignamos los datos a enviar Data mensaje_a_enviar = new Data().cmdCommand = Comandos. //Red del cliente public string Nombre. server. namespace Cliente { //Comandos para la interacción entre el servidor y el cliente enum Comandos { Login. byte[] byteData = mensaje_a_enviar.ComponentModel. Ventana del servidor cuando se conectan clientes y envían mensajes CÓDIGO FUENTE DEL PROYECTO CLIENTE using using using using using using using using using System.Text. //Nombre con el que el usuario entra al chat public EndPoint server. //Inicio de secion en el servidor Logout. //Cierre de sesión del servidor Mensaje. } catch (Exception) { .Length.Generic.None.Drawing.BeginSendTo (byteData. private void btnEnviar(object sender. System. SocketFlags. //Enviamos los datos encapsulados en mensaje_a_eviar clienteSocket.

case Comandos. break. } if (msgReceived. txtChatBox.Split('*')).EndSend(ar). } } //proseso al recibir un mensaje private void OnReceive(IAsyncResult ar) { try { clienteSocket. } } // proseso al enviar un mensaje private void OnSend(IAsyncResult ar) { try { clienteSocket. break.Items. .1).Login: lstChatters.Text += msgReceived.//en caso de no enviarse mostramos el siguiente mensaje MessageBox. case Comandos. "Cliente: " + Nombre.strMessage. MessageBoxButtons. } catch (ObjectDisposedException) {} catch (Exception ex) { MessageBox. //Convertimos los bytes recibidos en un objeto de tipo de datos Data Data msgReceived = new Data(byteData).AddRange(msgReceived.List) txtChatBox.Remove(msgReceived. MessageBoxButtons.Items. switch (msgReceived.Message. byteData = new byte[1024]. MessageBoxIcon.Show(ex.EndReceive(ar). case Comandos.Add(msgReceived.cmdCommand) { case Comandos.Error).cmdCommand != Comandos.Items.strMessage != null && msgReceived.List: lstChatters. "Cliente: " + Nombre.Show("Error al enviar mensaje".OK.Items. MessageBoxIcon.Items.OK.strMessage + "\r\n".RemoveAt(lstChatters.Logout: lstChatters.Text += "<<<" + Nombre + " bienbenido al grupo de chat >>>\r\n". lstChatters.strName).Error).Count .strName).Mensaje: break. break.

SocketFlags. SocketFlags. null). return. msgToSend. ref server. msgToSend. this. EventArgs e) { CheckForIllegalCrossThreadCalls = false.Error). new AsyncCallback(OnReceive).List. MessageBoxIcon. } } private void Form1_Load(object sender. ref server.Enabled = true. null).strName = Nombre. EventArgs e) { if (txtMessage.ToByte().Length.Enabled = false. "Cliente: " + Nombre. clienteSocket.OK.Text.BeginSendTo(byteData. } private void txtMessage_TextChanged(object sender. byteData. msgToSend. de modo que ahora solicitamos el servidor para enviar //los nombres de todos los usuarios que están en la sala de chat Data msgToSend = new Data (). FormClosingEventArgs e) { if (MessageBox. 0.No) { e.Length.Length. 0.BeginReceiveFrom(byteData. "Cliente : " + Nombre.Message. else btnSend.Cancel = true. //El usuario ha iniciado sesión en el sistema.YesNo. } catch (ObjectDisposedException) {} catch (Exception ex) { MessageBox. null).Show(ex.None.//para enpezar a recibir los datos de los demas usuarios clienteSocket. byteData = msgToSend. new AsyncCallback(OnSend).cmdCommand = Comandos.Text = "Cliente : " + Nombre. new AsyncCallback(OnReceive).Show("Desea salir de la sala de chat".strMessage = null. //Empezamos a recibir los datos de forma asincronica clienteSocket.BeginReceiveFrom (byteData.Length == 0) btnSend. byteData. } private void SGSClient_FormClosing(object sender.Exclamation) == DialogResult. SocketFlags.None. MessageBoxButtons. MessageBoxIcon. byteData. byteData = new byte[1024]. MessageBoxButtons. server.None. } try { . 0.

GetString(data.strName = null.strMessage = null.cmdCommand = Comandos. 0. byte[] b = msgToSend. KeyEventArgs e) { if (e.Message.Close(). } } //La estructura de datos por el cual el servidor y el cliente interactúan { //constructor por defecto public Data() { this. //Las cuatro siguientes almacén de la longitud del nombre int nameLen = BitConverter.//Envia un mensaje al cerrar sesión en el servidor Data msgToSend = new Data (). MessageBoxIcon.SendTo(b. } } } private void txtMessage_KeyDown(object sender. 0). } catch (ObjectDisposedException) {} catch (Exception ex) { MessageBox. msgToSend. "Cliente : " + Nombre. MessageBoxButtons.strMessage = null.ToByte (). //Las cuatro siguientes almacén de la longitud del mensaje int msgLen = BitConverter.strName = Encoding. 12. b.strMessage = Encoding. else this.ToInt32(data. 4).strName = Nombre.strName = null.Logout. } class Data //Convierte los bytes en un objeto de tipo Data public Data(byte[] data) { //Los primeros cuatro bytes son para el Comando this. server). } .UTF8.Error).cmdCommand = (Comandos)BitConverter. this. this. nameLen).Show(ex.Null. msgLen).Length. clienteSocket. else this.ToInt32(data.KeyCode == Keys. SocketFlags.Enter) { btnEnviar(sender. clienteSocket.UTF8.GetString(data.None. //Esto comprueba si hay un campo de mensaje nula if (msgLen > 0) this. /Esta comprobación se asegura de ese nombre de usuario ha sido aprobada en la matriz de bytes if (nameLen > 0) this.cmdCommand = Comandos.strMessage = null. 12 + nameLen.OK. 8). msgToSend.ToInt32(data. msgToSend. null).

AddRange(BitConverter.ToArray(). //tipo de comando (conexión.GetBytes(strName. desconexión.UTF8. //Nombre con el que el cliente se registra en la habitación public string strMessage.AddRange(BitConverter. //Mensaje public Comandos cmdCommand. else result.GetBytes(0)). //Añadir la longitud del nombre if (strName != null) result. else result. // por último añadimos el texto del mensaje a su matriz de bytes if (strMessage != null) result. //Añadir el nombre if (strName != null) result.GetBytes(strMessage)).GetBytes((int)cmdCommand)). enviar mensajes) } } CAPTURA DE PANTALLA DEL CLIENTE .Length)).GetBytes(strName)). //Cuatro primeros son para el Comando result.AddRange(BitConverter. //Longitud del mensaje if (strMessage != null) result.AddRange(BitConverter.AddRange(Encoding. public string strName.GetBytes(0)).AddRange(Encoding.AddRange(BitConverter.//Convierte la estructura de datos en una matriz de bytes public byte[] ToByte() { List<byte> result = new List<byte>().UTF8. } return result.Length)).GetBytes(strMessage.

Figura 1. Ventana del Login En la ventana principal del chat tendremos un listado de las personas conectadas de igual manera se pueden enviar y recibir mensajes los cuales se presentan en el textfield. Figura 4.En la ventana Login se establece el Nick y la IP del servidor al que se va a conectar que en este caso es la IP de la máquina que este corriendo la aplicación servidor. Ventana principal del chat .

.CONCLUSIONES La creación de esta aplicación nos llevó a investigar nuevas herramientas de programación para poder así implementar el protocolo UDP en programa de chat. aunque una desventaja es que se puedan perder algunos paquetes. esto fue algo positivo porque nos ayuda a crecer y obtener más experiencia como programadores. el cual fue realizado en el lenguaje C#. Nos queda como conclusión que UDP es un protocolo de trasporte que se usa cuando se buscan transmisiones con una cantidad de información baja en los paquetes y altas velocidades de transferencia. Estos nuevos métodos aprendidos nos sirvieron para concluir correctamente con el programa planteado.

es/jlgs/Docen/Transpas-TCP. ES. Formato HTML. (En línea).com/Temas/tcpip.alfinal. Formato PDF.BIBLIOGRAFIA Avogadro. Modelo TCP/IP. J. Disponible en: http://www. (En línea). Repositorio Institucional de la Universidad de Alicante. Consultado el 17 de octubre del 2016.pdf Candela. Protocolos UDP y TCP.unex. 2009. 2009. p 1-19 . Disponible en http://gitaca. Protocolos de transporte UDP y TCP. Consultado el 17 de abril de octubre del 2016. . E. F y Pomares.php Gonzales J. Alicante.