Compilació

De Wikijoan
Dreceres ràpides: navegació, cerca

Es tracta d'una aplicació client servidor d'echos, que vam realitzar en el Curs de Programació Linux de la ICE-UPC (Sergi Tur):

el servidor escolta els echos (missatges per pantalla) que li arriben dels clients. La única cosa que fa el servidor es mostrar per pantalla els missatges que li envien els clients. És un exercici de programació de sockets en C.

En la primera part compilarem el codi. Després l'executarem en un client i en un servidor per comprovar que funciona. Més tard farem que el servidor sigui un dimoni. I més tard en farem un paquet (el debianitzarem) per tal de poder distribuir-lo.

Codi. Compilació

El codi el podem descarregar de La Farga: https://lafarga.cpl.upc.edu/plugins/scmsvn/viewcvs.php/sessio5/ClientServerEcho/?rev=12&root=plinux

server.c

/*
http://xarxantoni.net:8080/mediawiki/index.php/Programaci%C3%B3_en_xarxes
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>      

//Aquí podeu escollir el port del servidor.
int port = 8000;

void main() {
  struct sockaddr_in sin;
  struct sockaddr_in pin;
  int sock_descriptor;
  int temp_sock_descriptor;
  int address_size=0;
  char buf[16384];
  int i, len;

  /*
  PF_INET/AF_INET Determinem IPv4 com la familia de protocols. Veieu man ip(7)
  SOCK_STREAM Mode orientat a connexió.
  0 Al fitxer /etc/protocols el protocol 0 és el IP.
  */
  sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
  if (sock_descriptor == -1) {
    perror("Error al cridar socket...");
    exit(1);
  }

  memset(&sin,0 , sizeof(sin));
  sin.sin_family = AF_INET;
  // INADDR_ANY ens permet fer el vincle amb qualsevol de les adreces IP del 
  // servidor.
  sin.sin_addr.s_addr = INADDR_ANY;
  //La comanda htons transforma un número de port en el format de xarxa. 
  sin.sin_port = htons(port);

  if (bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
    perror("Error al cridar bind...");
    exit(1);
  }

  if (listen(sock_descriptor, 20) == -1) {
    perror("Error al cridar listen...");
    exit(1);
  }

  printf("El servidor esta a l'espera de rebre connexions ...\n"); 

  // El bucle infinit fa que el servidor es quedi escoltant noves peticions 
  // permanentment. Cada nova petició, s'obra un nou socket per fer la 
  // la comunicació entre el client i el servidor.
  
  while(1) {
    temp_sock_descriptor =
      accept(sock_descriptor, (struct sockaddr *)&pin,
             &address_size);
    if (temp_sock_descriptor == -1) {
      perror("Error al cridar accept...");
      exit(1);
    }

    if (recv(temp_sock_descriptor, buf, 16384, 0) == -1) {
      perror("Error al cridar recv...");
      exit(1);
    }

    printf("S'ha rebut del client el següent String:%s\n", buf);

    if (send(temp_sock_descriptor, buf, strlen(buf), 0) == -1) {
      perror("Error al cridar send");
      exit(1);
    }

    close(temp_sock_descriptor);
  }
}

En el client he de posar la IP del servidor al que em vull connectar client.c

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

/* Aquí heu de declarar l'adreça IP i número de port 
del servidor */
//char * host_name = "127.0.0.1";
char * host_name = "192.168.1.130";
int port = 8000;

void main(int argc, char *argv[]) {
  char buf[8192];
  char missatge[256];
  int socket_fd;
  struct sockaddr_in sin;
  struct hostent *server_host_name;

  char * str;

  if (argc != 2) {
    printf("Utilitza: %s missatge\n",argv[0]);
    exit(1);
  } else {
    str = argv[1];
  }

  if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("Error creant el socket\n");
    exit(1);
  }  

  if ((server_host_name = gethostbyname(host_name)) == 0) {
    perror("Error resolent l'adreça del servidor\n");
    exit(1);
  }

  /*Inicialització de la variable sockaddr tal i com s'indica a 
   a man 2 bind*/
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_addr.s_addr = ((struct in_addr *)(server_host_name->h_addr))->s_addr;
  sin.sin_port = htons(port);

  if (connect(socket_fd, (void *)&sin, sizeof(sin)) == -1) {
    perror("Error conectant-se al socket\n");
    exit(1);
  }

  printf("Enviant missatge %s al servidor...\n", str);

  if (send(socket_fd, str, 8192, 0) == -1) {
    perror("Error enviant el missatge...\n");
    exit(1);
  }

  printf("..Misatge enviat .. esperant la resposta...\n");

  if (recv(socket_fd, buf, 8192, 0) == -1) {
    perror("Error reben la resposta del servidor...\n");
    exit(1);
  }
  
  printf("\nResposta del servidor: %s\n", buf);
  
  close(socket_fd);

}

i compilem:

$ sudo make

Compila bé excepte alguns warnings, es generer els executables client i server

Per fer la primera prova ho fem en la mateixa màquina. En un terminal obrim el server i en l'altre terminal el client:

$ ./server
El servidor esta a l'espera de rebre connexions ...
$ ./client hola
Enviant missatge hola al servidor...
..Misatge enviat .. esperant la resposta...

Resposta del servidor: hola

i en el servidor hem obtingut:

S'ha rebut del client el següent String:hola

Faig la prova en dos ordinadors diferents, i funciona bé.

Com que em connecto pel port 8000, des de la màquina client també em puc connectar al servidor per telnet:

$ telnet 192.168.1.130 8000
hola món
hola món -> resposta del servidor
GENT_PID=5477Connection closed by foreign host
$

5477 és el PID (identificador del procés):

$ ps aux | grep server
joan     19274  0.0  0.0   1544   368 pts/0    S+   10:14   0:00 ./server

Doncs no, el PID=19274

per fer un scanner dels ports, i veure que el 8000 està obert (ho faig en el client):

$ sudo apt-get install nmap
$ nmap 192.168.1.130
8000/tcp open http-alt

creat per Joan Quintana Compte, octubre 2008

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
IES Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines