• No se han encontrado resultados

Arquitecturas cliente/servidor

N/A
N/A
Protected

Academic year: 2021

Share "Arquitecturas cliente/servidor"

Copied!
46
0
0

Texto completo

(1)

Arquitecturas  cliente/servidor  

(2)

Contenido      

• 

Procesos  

• 

Semáforos  

• 

Sincronización  

• 

Lectura  y  Escritura  de  Archivos  

• 

Servidores  Orientados  a  Conexión  

• 

Servidores  No  Orientados  a  Conexión  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(3)

Procesos  

• 

Un  programa  en  ejecución  es  un  proceso.  

 

• 

Un  proceso  es  cualquier  secuencia  de  

operaciones  que  están  ejecutándose  en  

memoria  acPva,  realizando  una  o  varias  

instrucciones  sobre  ciertos  datos.  

(4)

Los  procesos  pueden  ser  concurrentes  

o  paralelos.  

 

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(5)

Programación  concurrente  

 

• 

Cada  proceso  representa  un  programa  secuencial  que  

ejecuta  una  serie  de  instrucciones.  

• 

Al  ejecutarse  un  programa  secuencial,  éste  sigue  un  solo  

“hilo  de  control”  (thread),  esto  es  se  inicia  con  una  

operación  atómica  (indivisible)  del  proceso  y  se  mueve  a  

través  del  proceso  conforme  las  operaciones  se  van  

(6)

Procesos  concurrentes  

• 

Procesos  disjuntos  

– 

Son  disjuntos  si  se  ejecutan  en  diferentes  bloques  

de  programa,  sin  posibilidad  de  accederse  entre  

sí.  Ambos  se  ejecutan  simultáneamente  y  

proceden  concurrentemente  hasta  que  alguno  o  

los  dos  terminan.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(7)

Procesos  cooperaPvos  

 

Tienen  la  necesidad  de  comunicarse  entre  sí  en  la  

realización  de  una  tarea,  comparPendo  recursos  en  

común  por  lo  que  requieren  alguna  forma  de  

(8)

Programación  paralela  

• 

Un  programa  paralelo  o  distribuido  es  aquel  formado  

por  varios  procesos  secuenciales  que  se  ejecutan  en  

varios  procesadores  conectados  entre  sí.  

• 

Si  la  red  se  forma  por  conexiones  dentro  de  una  sola  

computadora  se  considera  un  esquema  de  

programación  paralela.  

• 

Si  la  red  se  forma  por  conexiones  entre  diferentes  

computadoras  se  considera  un  esquema  de  

programación  distribuida.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(9)

Organización  de  memoria  

• 

En  un  sistema  mulPproceso  existen  recursos  

considerados  comunes  o  comparPdos  por  todos  

los  procesadores,  como  son  el  caso  de  la  

memoria  y  los  medios  periféricos.  

• 

La  comunicación  entre  los  procesos  se  clasifica  en  

dos  Ppos:  

Fuertemente  acoplados  

• 

Para  el  caso  en  que  el  grado  de  interacción  es  alto  

Débilmente  acoplados  

(10)

Comunicación  entre  procesos  

 

La  manera  como  la  memoria  es  “reparPda”  entre  

los  procesadores  determina  el  MECANISMO  DE  

COMUNICACIÓN  a  uPlizar:  

Variables  compar:das  

– 

En  caso  de  memoria  comparPda  y  por  lo  general  

procesos  fuertemente  acoplados.  

 

Paso  de  mensajes  

– 

En  caso  de  memoria  distribuida  y  por  lo  general  

procesos  bajamente  acoplados.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(11)

Memoria  comparPda  

• 

Un  sistema  mulPproceso  con  memoria  

comparPda  es  aquél  que  permite  el  acceso  de  

cualquier  procesador  del  sistema  a  cualquier  

localidad  de  memoria  común.  

• 

Cada  dirección  es  única  e  idénPca  para  todo  

(12)

• 

La  comunicación  entre  procesos  se  realiza  por  

lectura  y  escritura  

de  variables  en  la  misma  

sección  de  memoria.  

           Memoria  

Procesador  1  

 

 

P1  

 

 

 

 

P2  

 

 

 

 

P3  

 

 

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(13)

 

Memoria  comparPda  

 

• 

Para  asegurar  la  integridad  de  los  datos  en  

memoria  comparPda  son  necesarios:  

– 

Mecanismos  para  el  soporte  de  comunicaciones  

– 

Ambiente  de  programación  que  provea  la  

planeación  

– 

Localización  

– 

Sincronización    

(14)

Memoria  distribuida  

• 

Un  sistema  mulPprocesador  de  memoria  

distribuida   es   aquél   en   el   que   cada  

procesador   uPliza   su   propia   memoria  

privada.  

• 

La  comunicación  con  otros  procesadores  

mediante  una  red  de  interconexión.  

 

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(15)

Programación  Distribuida  

• 

La  comunicación  entre  procesos  se  realiza  

mediante  envío  y  recepción  de  datos.  Este  

(16)

Conceptos  de  programación  

concurrente  y  paralela  

 

EXCLUSION  MUTUA  

 

• 

Se  refiere  a  la  situación  en  que  dos  o  más  procesos  

comunicándose  entre  sí,  mantengan  la  integridad  de  

los  datos  que  comparten.    

– 

En  el  caso  de  variables  comparPdas,  es  la  serialización  de  

las  acciones  de  escritura  o  lectura  sobre  una  variable.    

– 

En  el  caso  de  paso  por  mensajes  se  refiere  a  que  cada  

proceso  es  capaz  de  recibir  un  solo  mensaje  a  la  vez.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(17)

Conceptos…  

 

CONDICIÓN  DE  COMPETENCIA  

 

• 

Dada  la  situación  de  exclusión  mutua  en  la  

comunicación  entre  procesos  se  hace  necesario  

que  los  procesos  “

compitan

”  entre  sí  para  tomar  

posesión  de  las  variables  comparPdas,  o  en  caso  

de  paso  de  mensajes  que  dos  o  más  procesos  

compitan  porque  su  mensaje  sea  recibido  antes  

por  un  tercer  proceso.  

(18)

Conceptos…  

JUSTICIA  

• 

Se  refiere  al  hecho  de  proporcionar  la  

oportunidad  a  todos  los  procesos  que  ejecuten  

sus  acPvidades  sin  que  ninguno  quede  

suspendido  o  bloqueado  permanentemente.  

GRANULARIDAD  

• 

Indica  la  canPdad  de  instrucciones  a  ejecutar  que  

cada  procesador  realiza  con  respecto  al  Pempo  

que  cada  proceso  tarda  en  comunicarse  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(19)

Conceptos…  

BALANCE  DE  TRABAJO  

• 

Para  lograr  un  trabajo  eficiente  y  una  distribución  

equitaPva  de  procesador(es)  es  necesario  aplicar  

técnicas  de  balance  de  trabajo  para  que  se  

distribuyan  lo  más  uniformemente  posibles  los  

procesadores.  

 

• 

Un  balance  de  trabajo  ópPmo  manPene  los  

procesadores  ocupados,  procurando  que  todos  

ellos  terminen  casi  al  mismo  Pempo.  

(20)

Conceptos…  

TERMINACION  

 

• 

Se  refiere  al  hecho  de  asegurar  que  todos  los  

procesos  de  un  programa  concurrente  

finalicen  correctamente.  

• 

Si  al  menos  uno  de  los  procesos  no  termina  

por  alguna  causa,  el  programa  concurrente  

simplemente  no  termina  con  éxito.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(21)
(22)

Abrazo  mortal  (dead  lock)  

• 

Un  programa  concurrente  se  encuentra  en  

abrazo  mortal  si  todos  sus  procesos  se  

encuentran  bloqueados  entre  sí,  es  decir,  

ninguno  puede  llegar  a  terminar  

• 

También  existe  otro  problema  llamado  inanición,  

que  es  cuando  un  proceso  no  puede  llegar  a  

ejecutarse,    en  el  ejemplo  de  los  filósofos  que  

nunca  pueda  comer  ya  que  no  puede  obtener  los  

dos  tenedores  necesarios.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(23)

Si  se  Pene  programación  paralela  eso  significa  que  ¿se  

puede  dividir  el  Pempo  de  procesamiento  en  el  

número  de  procesadores  existentes?  

P0  

P1  

P2  

P3  

   P0  

   P2  

   P1  

   P3  

(24)

Ley  de  Amdahl  

• 

Propone  normalizar  el  Pempo  que  toma  realizar  la  operación  en  un  solo  

procesador  al  valor  de  1.    

 

• 

La  fracción  del  cálculo  que  sólo  se  puede  realizar  secuencialmente  será  

F,  entonces  la  fracción  paralelizable  es1-­‐F.    

• 

Entonces,  el  incremento  de  velocidad  máximo  que  puede  obtenerse  

con  P  elementos  de  procesamiento  está  dado  por  la  ecuación:    

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(25)

El  caso  ideal…  

• 

Como  un  ejemplo,  si  nuestra  aplicación  no  

Pene  sección  secuencial  ,  entonces  el  

incremento  de  velocidad  máximo  estará  dado  

exactamente  por  el  número  de  elementos  de  

procesamiento:    

(26)

Programación  concurrente  y  

semáforos  en  Java  

• 

En  Java  es  posible  ejecutar  tareas  en  paralelo,  

uPlizando  hebras  de  control  (hilos,  threads).    

Este  modo  de  programación  permite  tener  un  

espacio  de  memoria,  código  o  recursos  

comparPdos.  Tiene  la  ventaja  que  su  

ejecución  resulta  más  económica  que  un  

proceso  completo.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(27)

Semáforos  

• 

Java  cuenta  con  semáforos  implícitos  de  la  forma:  

Object  mutex  =  new  Object();  

/*  …*/    

Synchonized  (mutex){  

/*  …  */  

}  

 

Que  solo  pueden  ser  uPlizados  para  exclusión  mutua.  

 

Solo  una  hebra  de  control  puede  ejecutarse  en  el  bloque  

synchonized  en  un  momento  dado.  

(28)

Ejemplo  del  uso  de  la  palabra  

Synchonized  

import  java.io.*;  

class  Banco  {    

 public  staPc  void  main  (  String  args[])  {  

     try  {    

   

 //  Declaramos  los  dos  montones  de  billetes    

   

 Contador  co1  =  new  Contador  ();  

     

 Contador  co2  =  new  Contador  ();    

   

 //  Declaramos  los  dos  cajeros    

   

 Cajero  c1  =  new    Cajero(co1);  

   

 Cajero  c2  =  new  Cajero(co2);  

   

   //  Se  ponen  a  contar..    

   

 c1.start();    

   

 c2.start();  

   

   c1.join();  

   

   c2.join();    

   }  catch  (  ExcepPon  e  ){  

   

   e.printStackTrace();  }  

   }  

 }  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(29)

Clase  Contador:  Cuenta  billetes  y  

almacena  la  suma  

class  Contador  {  

 int  numBilletes  =  0  ;    

 long  suma  =  0  ;  

 final  int  TOTAL_BILLETES  =  10000  ;  

 final  int  VALOR_BILLETES  =  200  ;    

 void  cuenta  ()  {      

   //  A  contar  la  suma  de  los  billetes    

   for  (  numBilletes  =0  ;  numBilletes  <  TOTAL_BILLETES;    

   

 numBilletes  ++  )  {  

   

   suma  +=  VALOR_BILLETES  ;  

   

   //  Billetes  de  200  pesos  Thread.yield();  }    

 

 System.out.println  

(  numBilletes+  "  suman  :  "+  suma  +    

   

 "  pesos");  

   }    

(30)

Clase  Cajero:  Recibe  cierta  canPdad  de  

billetes  para  contar  

class  Cajero  extends  Thread  {    

   

 Contador  contadorCajero  ;    

   

 Cajero  (  Contador  paramContador  )    

   {  

   

   contadorCajero  =  paramContador  ;  

     }  

   public  void  run  ()    

   {    

   

 contadorCajero.cuenta();  

     }  

   }    

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(31)

Resultado:  

• 

10000    suman  2000000  pesos  

• 

10000    suman  2000000  pesos  

 

Es  correcto,  dado  que  cada  cajero  Pene  su  

canPdad  de  billetes  para  contar.  

 

   

(32)

ComparPendo  el  recurso  

• 

Ahora  supongamos  que  los  dos  cajeros  deben  contar  del  mismo  montón,  o  sea,  lo  

comparten  y  por  tanto,  la  suma  de  lo  que  haya  contado  cada  uno  debe  ser  el  

resultado  total.  

• 

Para  ello,  modificaremos  el  código  añadiendo  lo  siguiente  

 

Declaramos  los  dos  montones  de  billetes  :  

 

– 

Contador  co1  =  new  Contador  ();    

     //  Ahora  sobra,  Contador  co2  =  new  Contador  ();    

 //  Declaramos  los  dos  cajeros  y  el  mismo  montón.    

 Cajero  c1  =  new  Cajero(co1);    

 Cajero  c2  =  new  Cajero(co1);    

 

Con  este  cambio  obtenemos:  

• 

10000  suman:  2000200  pesos  

• 

10001  suman:  2000200  pesos  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(33)

• 

El  resultado  anterior  es  incorrecto  

• 

Por  tanto,  debemos  uPlizar  un  mecanismo  de  

sincronización  que  garanPce  que  cuando  un  cajero  

cuente  un  billete  y  lo  sume,  el  otro  no  pueda  intentar  

coger  el  mismo  billete  y  sumarlo.  La  solución  que  

ofrece  Java  para  resolver  este  problema  es  de  lo  más  

simple  y  eficiente,  uPlizando  la  cláusula  synchronized  

en  la  declaración  del  método  donde  se  realiza  la  tarea  

"críPca".  

 

• 

Por  tanto,  cambiaremos  el  método  void  cuenta()  por:    

(34)

• 

Si  realizamos  ese  cambio,  obtenemos  el  

siguiente  resultado:  

• 

10000  suman  :  2000000  pesos  

• 

10000  suman  :  4000000  pesos  

• 

Esto  ocurre  porque  no  se  inicializa  la  variable  

suma  antes  del  ciclo  que  cuenta  los  billetes,  

por  lo  que  el  segundo  cajero  conPnúa  la  suma  

en  donde  la  dejó  el  anterior.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(35)

Inicializando  el  contador  dentro  de  

cada  

• 

Si  modificamos  el  código  e  incluimos  la  inicialización,  tendremos:  

 

 

void  cuenta  ()  {  

   //  Cada  cajero  cuenta  lo  suyo  …    

 suma  =  0  ;    

 //  A  contar  la  suma  de  los  billetes  

   for  (  numBilletes  =0  ;  numBilletes  <  TOTAL_BILLETES  ;numBilletes  ++  )  

     {  

   

   suma  +=  VALOR_BILLETES  ;    

   

 Thread.yield();  

     }  

 }  

   

A  parPr  de  este  momento  obtenemos  el  siguiente  resultado  esperado  tal  y  como  detallamos:  

10000  suman  :  2000000  pesos  

(36)

• 

Otra  forma  de  realizar  la  sincronización  consiste  en  declarar  el  

objeto  comparPdo  como  sincronizado  en  vez  del  método  que  lo  

conPene.  Se  realiza  entonces  el  siguiente  cambio:    

 

 public  void  run(){    

   contadorCajero.cuenta();  

   }  

 por:  

 public  void  run(){  

     synchronized  (contadorCajero  )  {    contadorCajero.cuenta();    

   }  

   }    

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(37)

Monitores  

• 

El  siguiente  nivel  dentro  de  la  solución  a  los  

problemas  de  exclusión  mutua  y  sincronización  

entre  procesos  concurrentes  fue  desarrollado  por  

C.A.R.  Hoare  y  P.  Brinch  Hansen.  

• 

Ahora  se  considera  como  recurso  comparPdo  no  

únicamente  las  variables  comparPdas,  sino  

también    a  los  procedimientos  y  funciones  que  

actúan  sobre  las  variables  

(38)

Seudocódigo  

• 

Notación  propuesta  por  Hoare  (Simula  67)  

monitorname:  monitor  

 begin    

                                                           //declaraciones  de  datos  locales  del  monitor  

   procedure              

//procname  {  parametros  formales  }  

     begin        

//  cuerpo  del  procedimiento  

               …            

//  otros  procedimiento  locales  del  monitor  

     end  

   …  

   ..                                            

//inicialización  de  los  datos  locales  del  monitor  

       end  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(39)

Monitores  

(40)

Ejemplo  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(41)

:TubTest   t:Tuberia   p:Productor   c:Consumidor   new  Tuberia()   new    Productor(t)   new    Consumidor(t)   start(  )   start(  )   run(  )   run(  )   lanzar(c  )   lanzar(c  )   recoger(c  )  

…  

…  

sleep(  )   sleep(  )   estaVacia  ==  false   siguiente++   estaLlena==false   siguiente-­‐-­‐   estaVacia  ==  false   siguiente++  

…  

…  

(42)

:TubTest   t:Tuberia   p:Productor   c:Consumidor   new  Tuberia()   new    Productor(t)   new    Consumidor(t)   start(  )   start(  )   run(  )   run(  )   lanzar(c  )   lanzar(c  )   recoger(c  )  

…  

…  

sleep(  )   sleep(  )   (estaVacia==true)?   estaVacia==  false  

…  

…  

…  

wait()   noPfy()   estaLlena==false   siguiente-­‐-­‐  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(43)

Lectura  y  Escritura  de  Archivos  

import  java.io.BufferedInputStream;  

import  java.io.BufferedOutputStream;  

import  java.io.FileInputStream;  

import  java.io.FileOutputStream;  

 

 

public  class  LecturaEscrituraArchivos  {  

         

 

       public  staPc  void  main(String  args[]){  

               copiaArchivo("c:/archivoEntrada.txt",  "c:/archivoSalida.txt");  

       }  

         

• 

   

(44)

 public  staPc  void  copiaArchivo  (String  archivoLectura,  String  archivoEscritura){  

               try{              

                       FileInputStream  fileInput  =  new  FileInputStream(archivoLectura);  

                       BufferedInputStream  bufferedInput  =  new  BufferedInputStream(fileInput);  

                         

                       FileOutputStream  fileOutput  =  new  FileOutputStream(archivoEscritura);  

                       BufferedOutputStream  bufferedOutput  =  new  BufferedOutputStream(fileOutput);  

                       byte  []  array  =  new  byte  [1];  

                       int  leidos=  bufferedInput.read(array);  

                       while(leidos  >  0){  

                               bufferedOutput.write(array);  

                               leidos=bufferedInput.read(array);  

                       }  

                       bufferedInput.close();  

                       bufferedOutput.close();  

                         

               }catch(ExcepPon  e){  

                       e.printStackTrace();  

               }  

       }    

}  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

(45)

RandomAccessFile  

• 

Mediante  los  objetos  de  esta  clase  uPlizamos  

archivos  binarios  mediante  un  acceso  aleatorio,  

tanto  para  lectura  como  para  escritura.    

• 

Existe  un  índice  que  nos  indica  en  qué  posición  

del  archivo  nos  encontramos,  y  con  el  que  se  

puede  trabajar  para  posicionarse  en  el  archivo.  

• 

RandomAccessFile(String  nombre,  String  modo)  

– 

nombre:  cadena  idenPficadora  del  archivo  

– 

modo:  si  será  de  lectura  y/o  escritura  

(46)

Ejemplo  de  algunos  métodos  de  

escritura  

• 

La  escritura  del  archivo  se  realiza  con  una  función  que  depende  el  Ppo  de  datos  que  se  desee  

escribir.  

• 

void  write(  byte  b[],  int  ini,  int  len  );  Escribe  len  caracteres  del  vector  b.  

• 

void  write(  int  i  );  Escribe  la  parte  baja  de  i  (un  byte)  en  el  flujo.  

• 

void  writeBoolean(  boolean  b  );  Escribe  el  boolean  b  como  un  byte.  

• 

void  writeByte(  int  i  );  Escribe  i  como  un  byte.  

• 

void  writeBytes(  String  s  );  Escribe  la  cadena  s  tratada  como  bytes,  no  caracteres.  

• 

void  writeChar(  int  i  );  Escribe  i  como  1  byte.  

• 

void  writeChars(  String  s  );  Escribe  la  cadena  s.  

• 

void  writeDouble(  double  d  );  Convierte  d  a  long  y  le  escribe  como  8  bytes.  

• 

void  writeFloat(  float  f  );  Convierte  f  a  entero  y  le  escribe  como  4  bytes.  

• 

void  writeInt(  int  i  );  Escribe  i  como  4  bytes.  

• 

void  writeLong(  long  v  );  Escribe  v  como  8  bytes.  

• 

void  writeShort(  int  i  );  Escribe  i  como  2  bytes.  

• 

void  writeUTF(  String  s  );  Escribe  la  cadenas  UTF  

• 

Para  la  lectura  existen  métodos  análogos  para  leer  cada  uno  de  los  Ppos  de  datos.  

Arquitecturas  Cliente/Servidor,  Sem  2015-­‐1   M.I.Yasmine  Macedo  Reza      

Referencias

Documento similar

abstracción de recursos, donde cada petición HTTP contiene toda la información necesaria para responder a la petición, sin necesidad de que el cliente ni el servidor

El diagrama de despliegue para este sistema incluye la representación de una PC que realiza la función de servidor y una o más PCs Cliente conectadas al Servidor por medio

El servidor de peticiones retorna la unidad de tra- bajo creada para el cliente (ver caso de uso Atender Tarea Asignada por el Servidor Central. Sección Crear una Unidad de

Otro ejemplo son las “Librerías de cliente/servidor” que son las que permiten hacer llamadas a funciones del servidor desde el cliente usando las funciones JavaScript

Si se realiza un estudio de la Telefonía Móvil, las Comunicaciones Inalámbricas, la arquitectura Cliente – Servidor, así como de las tendencias actuales de las plataformas

La implementación del sistema se basa en un esquema cliente-servidor mediante un flujo de operaciones que completan el siguiente proceso: en el cliente se recopilan todos los datos

El desarrollo de la presente Tesis, se ha basado en el diseño e implementación de una aplicación cliente-servidor que permitiera al cliente gestionar de forma dinámica la reserva

Se indica, para cada flujo y sentido (cliente-servidor y servidor-cliente para los juegos, sólo este último para el streaming, punto a punto para VoIP), tanto el tamaño medio de