Esempi di comunicazione via socket

Di seguito è riportato il codice sorgente in linguaggio C di due programmi che esemplificano la comunicazione via rete mediante i socket. Il programma server resta in ascolto sulla porta 12345 di connessioni da parte di un client; quando il client si connette invia una stringa di testo che il server visualizza sul suo terminale, poi torna ad accettare una nuova connessione da parte di un client. Il client si connette, invia la stringa di testo fornita dall'utente come argomento sulla linea di comando e si sconnette dal server.

Il programma server si chiama server.c e deve essere compilato con il seguente comando: gcc server.c -o server. In questo modo viene prodotto il programma eseguibile server.

Il programma client si chiama client.c e deve essere compilato con il comando: gcc client.c -o client. Viene così prodotto il programma eseguibile client.

Per eseguire il sistema si deve lanciare, in due finestre distinte, per primo il programma ./server e poi, nella seconda finestra, il programma ./client, passando sulla linea di comando un testo delimitato dalle virgolette: ./client "Buon giorno server!"

Il programma Server

/*
**  server.c
**  
**  Esempio di comunicazione via socket.
**  Componente server. Ascolta sull'indirizzo di
**  loopback (127.0.0.1) sulla porta TCP 12345.
**
**  #(@)20150312(liverani@mat.uniroma3.it)
*/

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define SERVERPORT 12345
#define SERVERADDRESS "127.0.0.1"
#define MAX 32

int main(int argc, char * argv[]) {
  int serverSocket, connectSocket, returnCode;
  socklen_t clientAddressLen;
  struct sockaddr_in serverAddress, clientAddress;
  char buffer[MAX];
  char *clientIP;
  
  /* apertura socket del server */
  if (((serverSocket = socket(AF_INET,SOCK_STREAM,0))) == -1) {
    perror("Error in server socket()");
    exit(-1);
  }
    
  /* preparazione dell'indirizzo locale del server */
  serverAddress.sin_family = AF_INET;
  serverAddress.sin_port = htons(SERVERPORT);
  serverAddress.sin_addr.s_addr = inet_addr(SERVERADDRESS);
  
  /* bind del socket */
  if ((returnCode = bind (serverSocket, (struct sockaddr*)  &serverAddress, sizeof(serverAddress))) == -1) {
    perror("Error in server socket bind()");
    exit(-1);
  }
  
  /* listen del socket */
  if ((returnCode = listen(serverSocket, 1)) == -1) {
    perror("Error in server socket listen()");
    exit(-1);
  }
  
  printf("Server ready (CTRL-C per terminare)\n");
  
  clientAddressLen = sizeof(clientAddress);
  
  /* ciclo infinito in attesa di connessione */
  while (1) {

    /* accetta le connessioni */
    if ((connectSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &clientAddressLen)) == -1) {
      perror("Error in accept()");
      close(serverSocket);
      exit(-1);
    }
    
    /* memorizzo l'indirizzo del client in formato stringa */
    clientIP = inet_ntoa(clientAddress.sin_addr);
    
    printf("\nClient @ %s connects on socket %d\n", clientIP, connectSocket);
    
    /* riceve i messaggi e li stampa in output */
    while ((returnCode = read(connectSocket, buffer, MAX-1)) > 0) {
      buffer[returnCode] = '\0'; // buffer dev'essere una stringa e va terminata con '\0'
      printf(">> %s: %s\n", clientIP, buffer);
    }
    
    /* chiudo il socket */
    close(connectSocket);
  }
  return(0);
}
      

Il programma Client

/*
**  client.c
**      
**  Esempio di comunicazione via socket.
**  Componente client. Si connette all'indirizzo
**  di loopback (127.0.0.1) sulla porta TCP
**  12345 dove e' in ascolto il server.
**
**  #(@)20150312(liverani@mat.uniroma3.it)
*/

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define SERVERPORT 12345
#define SERVERADDRESS "127.0.0.1"

int main(int argc, char *argv[]) {
  int clientSocket;
  struct sockaddr_in serverAddress;
  char *msg;
  size_t msglen;
  int returnCode;
  
  /* verifico la correttezza dei parametri */
  if (argc != 2) {
    printf("Usage: %s \"message to send\"\n", argv[0]);
    exit(-1);
  }
  
  /* preparo la variabile msg in base alla dimensione del messaggio inserito dall'utente */
  msg = malloc(strlen(argv[1])*sizeof(char));
  
  /* apertura socket del client */
  if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("Error in socket()");
    exit(-1);
  }
  
  /* preparazione dell'indirizzo del server con cui connettere il socket */
  serverAddress.sin_family = AF_INET;
  serverAddress.sin_port = htons(SERVERPORT);
  serverAddress.sin_addr.s_addr = inet_addr(SERVERADDRESS);
  
  /* connessione del socket al server */
  if ((connect(clientSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress))) == -1) {
    perror("Error in connect()");
    exit(-1);
  }
  
  printf("Client connected to %s\n", SERVERADDRESS);
  
  /* invio messaggio al server */
  strcpy(msg, argv[1]); 
  msglen = strlen(msg)+1;
  returnCode = write(clientSocket, msg, msglen);
   
  printf("Sent %d (%u request) bytes on socket %d\n", returnCode, (unsigned) msglen, clientSocket);
  return(0);
}