[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[OT] Socket BSD su TCP in C



Scusate l'OT, ma ho provato su alcuni forum di programmazione C, poi ho
provato a guardare i sorgenti di un paio di server ftp e alla fine sono
alla frutta.

Devo modificare un programma C in modo che si metta in ascolto su una
qualsiasi porta TCP libera (> 1023) e comunichi al client (già connesso su
un'altra porta nota), qual è la nuova porta aperta. Discorso identico alla
modalità passiva dell'ftp.

Il codice dei server FTP che ho visto "risolve" il problema tentando la
chiamata a bind()+listen() su porte scelte a caso dall'applicazione. A me
sembra veramente una soluzione idiota. Va bene che funziona, ma cosa ci sta
a fare il sistema operativo?

Alcuni post raccolti qua e là mi hanno fatto sapere che impostando a zero il
valore di sin_port nella struttura sockaddr_in prima di chiamare la bind(),
ottengo che il sistema scelga una porta per me. Molto bene. Ma poi come
faccio a sapere quale porta ha scelto? Ho provato a fare il programmino di
esempio, sperando che mi impostasse il valore scelto al posto dello 0, ma
nulla, rimane a 0 (notare che il programmino qui sotto è una versione
ridotta in cui ho tolto quasi tutti i controlli di condizioni d'errore per
brevità, ma nella versione full gli errori non si verificano comunque):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
  int r;
  struct addrinfo hints, *ai, *aitop;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = PF_INET;
  hints.ai_socktype = SOCK_STREAM;
  r = getaddrinfo("localhost", "0", &hints, &aitop);
  
  for (ai = aitop; ai; ai = ai->ai_next)
  {
    int sock;
    
    sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (sock < 0) /* ipv6 non supportato */
      continue;
    
    ((struct sockaddr_in *)(ai->ai_addr))->sin_port = htons(0);  
    bind(sock, ai->ai_addr, ai->ai_addrlen);
    listen(sock, 5);
    printf("Ascolto sulla porta %d\n", (int)((struct sockaddr_in *
(ai->ai_addr))->sin_port);
  }

  return EXIT_SUCCESS;
}

Qual'è l'output?

Ascolto sulla porta 0

Sarà perché il networking l'ho imparato prima in Java, ma mi aspetto che una
cosa del genere sia possibile senza mettersi a fare cicli tentando la
fortuna...



Reply to: