Saltar al contenido
Codifíca.me | Desarrollo web | Programación

Socket TCP | Ejemplo de Cliente a Servidor y Servidor a Servidor

2 octubre, 2012

En este artículo vemos el código necesario para crear un esquema Cliente-Servidor-Servidor utilizando el protocolo TCP, realizado en Java utilizando varios Sockets.

Cómo ya sabéis el protocolo TCP está orientado a conexión, para más información podéis ver este link.
Información general de la Wikipedia:
Socket Wikipedia

Socket TCP

En el ejemplo el cliente va a llamar a un servidor que llamará al otro, como si fuese una cadena. Después el último devolverá la respuesta al anterior y el anterior al cliente inicial.

El funcionamiento sería así:
– El cliente se conecta con el servidor A.
– El servidor A transmite la petición del cliente al servidor B.
– El servidor B envía su respuesta al servidor A.
– El servidor A transfiere la respuesta del servidor A al cliente.

Código del Servidor A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
 
import java.net.*; //Importa la libreria java.net
import java.io.*;  //Importa la libreria java.io
 
public class servidortcp {
   //se declara una clase de nombre servidortcp
 
	public static void main(String argv[]) {
            //Se declara el método principal main que espera un parámetro
 
		System.out.println("SERVIDOR");
	    ServerSocket socket;   //Se crea un objeto de ServerSocket
      //boolean fin = false; //Se declara una variable booleana inicializada a false
 
 
      try {
    	  //Abrimos una exceptción para el tratamiento de errores
          //Creamos un servidor 
    	  socket = new ServerSocket(6004); //Abre un socket en modo escucha en el puerto 6001
          Socket socket_cli = socket.accept(); //Inicio.Se acepta la conexión.
 
         //Método de la clase socket para recibir datos
         DataInputStream in =
            new DataInputStream(socket_cli.getInputStream());
 
         //Método para mandar un valor al cliente
         DataOutputStream out =
             new DataOutputStream(socket_cli.getOutputStream());
 
 
         String mensaje =""; //Se inicializa la variable de string mensaje a vacío
         mensaje = in.readUTF(); //La variable Mensaje guarda el valor que ha mandado el cliente
 
         if (mensaje.startsWith("HELLO")) {
        	 out.writeUTF("HELLO");
         }
 
         do {
 
        	 //Estará escuchando el mensaje sin interrupción debido a la condición (1>0) del while
            mensaje =""; //Se inicializa la variable de string mensaje a vacío
            mensaje = in.readUTF(); //La variable Mensaje guarda el valor que ha mandado el cliente
 
            if (mensaje.startsWith("ALL")) {
 
            	mensaje = "ALL BUR:250;CHE:300; BIG:540; PAT:380; SAL:240; BEV:210; DIE:0; COF:0; DES:300";
            	System.out.println(mensaje);
 
            }
            else if(mensaje.startsWith("BUR"))
            {
            	mensaje = "BUR 250";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("CHE")) {
            	mensaje = "CHE 300";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("BIG")) {
            	mensaje= "BIG 540";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("PAT")) {
            	mensaje= "PAT 380";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("SAL")) {
            	mensaje= "SAL 240";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("BEV")) {
            	mensaje= "SAL 210";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("DIE")) {
            	mensaje= "DIE 0";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("COF")) {
            	mensaje= "COF 0";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("DES")) {
            	mensaje= "DES 300";
            	System.out.println(mensaje);
            }
            else if (mensaje.startsWith("fin")) {
            	mensaje= "fin";
        	    System.out.println(mensaje);
            }
            else{
                mensaje = "ERROR";	
            	System.out.println(mensaje);
            }
 
            //Mandamos al cliente la respuesta de las calorias según lo que ha mandado 
            out.writeUTF(mensaje);
            //System.out.println(mensaje); 
 
         } while (1>0);
      }
      catch (Exception e) {
    	  //Si se produce algún error saltará la excepción con el mensaje de error
         System.err.println(e.getMessage());
         System.exit(1); //Salimos con error
      }
   }
}

Código del Servidor B:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
 
import java.net.*; //Importa la libreria java.net
import java.io.*;  //Importa la libreria java.io
 
public class servidor3tcp {
 
 
	public static void main(String argv[]) {
        //Se declara el método principal main que espera un parámetro
 
 
	//Cuando se indica el servidor2 se hace refencia a servidortcp.java	
 
    //Declaración de variables necesarias
    Socket socket;   //Se crea un objeto de ServerSocket
    InetAddress address; //Se crea un objeto de tipo InetAddress
    ServerSocket socket3;   //Se crea un objeto de ServerSocket
    String mensaje ="HELLO"; //Se usará para comunicarse con el cliente
    String mensajeServidor=""; //Se usará para almacenar el resultado obtenido del servidor2 
    String mensajeServidor2=""; //Se usará para almacenar el resultado obtenido del servidor2 para el pedido2
    String mensaje3=""; //Almacenará el resultado final enviado al cliente
    String CaloriaPedido2="";  //Contendrá las calorias del pedido 2
    String CaloriaPedido1=""; //Contendrá las calorias del pedido 1
 
    //Otras variables para calcular la suma de calorias
    int longMensaje;  //En esta variable se almacenará el tamaño del mensaje
    String Pedido1="";  //Guardará el string del pedido 1
    String Pedido2="";  //Guardará el string del pedido 2
 
    //Guardará el valor de las calorias y el total. Pos y Pos1 indicarán la posición 
    //donde habrá que empezar para contar las cadena recibida
    int iCaloriaPeiddo2, iCaloriaPeiddo1, iTotalCalorias, pos, pos1=0;
 
  try {
 
	  //Dirección del servidor
	  address=InetAddress.getByName(argv[0]);
 
      //Creamos un servidor para el cliente
	  socket = new Socket(address,6004);
 
	  DataInputStream in = new DataInputStream(socket.getInputStream());
      DataOutputStream out = new DataOutputStream(socket.getOutputStream());
 
      //Mandamos el saludo al servidor2
	  out.writeUTF("HELLO");
 
      //Recojemos el resultado del servidor2
	  mensajeServidor = in.readUTF();
	  System.out.println(mensajeServidor);
 
      //Creamos el socket "servidor" para comunicarnos con el cliente
      socket3 = new ServerSocket(6001);
 
     //Aceptamos la conexión al servidor2 y nos preparamos para recibir datos suyos
 	 Socket socketClient = socket3.accept();
     DataInputStream in2 = new DataInputStream(socketClient.getInputStream());
	 DataOutputStream out2 = new DataOutputStream(socketClient.getOutputStream());
 
 
	 //Leemos del cliente esperando el saludo inicial
	 mensaje = in2.readUTF();
 
	 if (mensaje.startsWith("HELLO")) 
    	 out2.writeUTF("HELLO");
 
 
     do {
 
    	//Estará escuchando el mensaje sin interrupción debido a la condición (1>0) del while
 
		 mensaje = in2.readUTF();
		 System.out.println(mensaje);
 
		 //Limpiamos las variables utilizadas.
		 iCaloriaPeiddo2=0;
		 iCaloriaPeiddo1=0;
		 longMensaje=0;
 
		  //Para separar las dos descipciones calcularemos el tamaño de la cadena
		  //y buscaremos un espacio que las separa, después cogeremos la segunda cadena
		  //emepzando por la posición +1, para poder saltar el espacio en blanco
 
		  longMensaje = mensaje.length();
		  pos= mensaje.indexOf(' ');
 
		  if (pos > 0) {
 
			//Si es mayor que cero se han recibido dos palabras  
			//Separamos el contenido enviado para calcular la suma de calorias  
 
			//Obtenemos la descripción de los dos pedidos  
 
			//Segundo pedido  
			Pedido2 = mensaje.substring(pos+1, longMensaje); 
 
		    //Primer pedido
		    Pedido1 = mensaje.substring(0,pos);
 
		    //Calculamos las calorias del pedido2 
		    out.writeUTF(Pedido2);
 
		    //Recogemos el resultado del servidor2
		    mensajeServidor2 = in.readUTF();
 
			//Se calcula el tamaño del resultado del Pedido2
			longMensaje = mensajeServidor2.length();
			pos1= mensajeServidor2.indexOf(' ');
 
		    if ((pos1 < 0) || mensajeServidor2.startsWith("ERROR") || mensajeServidor2.startsWith("ALL")){
		    	//Si se ha recibido del servidor2 la palabra error, o la palabra ALL, las calorias serán 99999
		    	CaloriaPedido2 = "ERROR";
		    	mensajeServidor2 = Pedido2 + " " + "ERROR";
		    	iCaloriaPeiddo2 = 9999;
		    }
		    else{
		       //Separamos las calorias del pedido2
			   CaloriaPedido2 = mensajeServidor2.substring(pos1+1, longMensaje);
			   //Valor numérico de las calorias del pedido2
			   iCaloriaPeiddo2 = Integer.parseInt(CaloriaPedido2.trim());
		    }
 
			//Calculamos las calorias del pedido1 
		    //Le mandamos al servidor2 el literal del Pedido1
		    out.writeUTF(Pedido1);
 
			//Obtenemos el resultado del servidor2
		    mensajeServidor = in.readUTF();
 
			//Se calcula el tamaño del resultado del Pedido1
			longMensaje = mensajeServidor.length();
			pos1= mensajeServidor.indexOf(' ');
 
			if ((pos1 < 0) || mensajeServidor.startsWith("ERROR") || mensajeServidor.startsWith("ALL")){
		    	//Si se ha recibido del servidor2 la palabra error, o la palabra ALL las calorias serán 99999
				CaloriaPedido1 = "ERROR";
				mensajeServidor = Pedido1 + " " + "ERROR";
		    	iCaloriaPeiddo1 = 9999;
		    }
		    else{
			  //Separamos las calorias del pedido1
			  CaloriaPedido1 = mensajeServidor.substring(pos1+1, longMensaje);
			  //Valor numérico de las calorias del pedido1
			  iCaloriaPeiddo1 = Integer.parseInt(CaloriaPedido1.trim());
		    }
 
			//Calculamos el total de las calorias
			if(iCaloriaPeiddo2 == 9999 || iCaloriaPeiddo1 == 9999){
				//Si uno de los dos pedidos es erroneo el total de calorias será 9999
				iTotalCalorias = 9999;
			}
			else
			  iTotalCalorias = iCaloriaPeiddo1 + iCaloriaPeiddo2;
 
			System.out.println(mensajeServidor);
			System.out.println(mensajeServidor2);
			//Se crea el mensaje final con los dos pedidos y la suma de sus calorias.
			 mensaje3 = Pedido1 + " " + Pedido2 + " " + iCaloriaPeiddo1 + " " + iCaloriaPeiddo2 + " = " + iTotalCalorias;
 
			//Imprimimos en el servidor3 el total
			 System.out.println(mensaje3);
 
			//Le mandamos al cliente el total de calorias de los dos productos.
			 out2.writeUTF(mensaje3);
		  }
		  else{
			 //Si es menor que 0 solo se habrá recibido una palabra 
			 //Le mandamos al servidor2 la descripción
		     out.writeUTF(mensaje);
 
			 //Recojemos del servidor2 el resultado
			 mensajeServidor = in.readUTF();
			 System.out.println(mensajeServidor);
 
			 //Le mandamos al cliente el resultado que nos ha dado el servidor2
			 out2.writeUTF(mensajeServidor);	
		  }
 
     } while (1>0);
  }
  catch (Exception e) {
	  //Si se produce algún error saltará la excepción con el mensaje de error
     System.err.println(e.getMessage());
     System.exit(1); //Salimos con error
  }
}
}

Código del Cliente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 
 
import java.net.*; //Se importa la libreria java.net
import java.io.*; //Se importa la libreria java.io
 
//Se declara la clase clientetcp
public class clientetcp {
 
	//Se declara el método principal main que recibe un parámetro
   public static void main(String argv[]) {
 
	   //Si no recibe ningún parámetro dará error
	   if (argv.length == 0) {
         System.err.println("java clientetcp servidor");
         System.exit(1);
      }
 
	   System.out.println("CLIENTE");
 
	  // Se guarda en el buffer un valor introducido por pantalla  
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 
      Socket socket=null; //Se crea un objeto de tipo socket
      InetAddress address; //Se crea un objeto de tipo InetAddress
      String mensaje=""; //Se declara una variable de tipo string
 
      try {
             //Se abre una excepción
    	  //Obtiene el nombre de la dirección remota del socket
         address=InetAddress.getByName(argv[0]);
 
       	 socket = new Socket(address,6001); //Se crea un objeto de tipo socket 
                                            //para establecer una conexión por el puerto 6001
 
 
         //Se declara un objeto de tipo DataOutputStream para mandar valores al servidor 
         DataOutputStream out =
            new DataOutputStream(socket.getOutputStream());
 
         //Se declara un objeto de tipo DataOutputStream para mandar obtener al servidor
         DataInputStream in2 =
             new DataInputStream(socket.getInputStream());
 
         //Mandamos la palabra HELLO al servidor
         out.writeUTF("HELLO");
         //Recogemos lo que nos devuelve el servidor y lo guardamos en la variable mensaje
         mensaje = in2.readUTF();
         System.out.println(mensaje); //Imprime el contenido de mensaje
 
         do {
        	 //Mientras el mensaje no sea fin seguira leyendo
            mensaje = in.readLine();
            out.writeUTF(mensaje);
            //System.out.println(mensaje); //Imprime el contenido de mensaje
 
          //NUEVO
            mensaje =""; //Se inicializa la variable de string mensaje a vacío
            mensaje = in2.readUTF();
            System.out.println(mensaje); //Imprime el contenido de mensaje
          //NUEVO
 
         } while (!mensaje.startsWith("fin"));
 
      }
      catch (Exception e) {
         System.err.println(e.getMessage());
         System.exit(1);
      }
   }
}