Newsgroup: it.comp.os.unix
Titolo: IP address del client socket?

Salve a tutti,
che voi sappiate, esiste un metodo per leggere l'IP address dei client che
si collegono via socket?
Uso gcc su SunOS.
Segue la funzione che utilizzo per ascoltare le connessioni:
int get_connection(int socket_type, u_short port, int* listener)
{
  struct sockaddr_in address;
  int listening_socket;
  int connected_socket = -1;
  int new_process;
  int reuse_addr = 1;
  /* Setup internet address information.
     This is used with the bind() call */
  memset((char *) &address, 0, sizeof(address));
  address.sin_family = AF_INET;
  address.sin_port = port;
  address.sin_addr.s_addr = htonl(INADDR_ANY);
 
 
  listening_socket = socket(AF_INET, socket_type, 0);
  if (listening_socket < 0) {
    perror("\nsocket");
    return(-1);
  }
  if (listener != NULL)
    *listener = listening_socket;
  setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (const
void*)&reuse_addr,
    sizeof(reuse_addr));
  if (bind(listening_socket, (struct sockaddr *) &address,
    sizeof(address)) < 0) {
    perror("\nbind");
    close(listening_socket);
    return(-1);
  }
 
 
  if (socket_type == SOCK_STREAM) {
    listen(listening_socket, 5); /* Queue up to five connections before
                                  having them automatically rejected. */
    while(connected_socket < 0) {
      connected_socket = accept(listening_socket, NULL, NULL);
      if (connected_socket < 0) {
        /* Either a real error occured, or blocking was interrupted for
           some reason. Only abort execution if a real error occured. */
        if (errno != EINTR) {
          perror("\naccept");
          close(listening_socket);
          exit(EXIT_FAILURE);
        } else {
          continue; /* don't fork - do the accept again */
        }
      }
      new_process = fork();
      if (new_process < 0) {
        perror("\nfork");
        close(connected_socket);
        connected_socket = -1;
      }
      else { /* We have a new process... */
        if (new_process == 0) {
          /* This is the new process. */
          close(listening_socket); /* Close our copy of this socket */
	  if (listener != NULL)
	          *listener = -1; /* Closed in this process. We are not
				     responsible for it. */
        }
        else {
          /* This is the main loop. Close copy of connected socket, and
             continue loop. */
          close(connected_socket);
          connected_socket = -1;
        }
      }
    }
    return connected_socket;
  }
  else
    return listening_socket;
}
Grazie per le risposte!
---
http://www.gianlucabove.com
--------------------------------
Inviato via 
http://usenet.libero.it

 si collegono via socket?
Ci mancherebbe di no. :-)
accept() ha due parametri in piu` che son quelli che ti servono.
Il primo deve essere  un puntatore ad una struct sockaddr esistente 
(struct sockaddr_in, per IP), e il secondo e` la dimensione in byte 
della struttura (sizeof(struck sockaddr_in)).
Dopodiche` ti ritrovi con la tua struct sockaddr_in avvalorata, il cui 
membro sin_port ti da la porta remota, e il membro sin_addr l'indirizzo 
IP (analogamente a come vien fatto per bind()).
-- 
   |   \    \  | ___|_  |_  | ianezz a casa sua... :-)
   |  _ \  | \ | _|    /   /  Visita il LinuxTrent a
  _|_/  _\_|  _|____|___|___| 
http://www.linuxtrent.it

 IP (analogamente a come vien fatto per bind()).
dunque, il man di accept() dice che i parametri sono di tipo sockaddr (non
sockaddr_in) e quindi:
struct sockaddr {
        sa_family_t sa_family; /* address family */
        char sa_data[14]; /* up to 14 bytes of direct address */
};
ora il problema è: come faccio a interpretare i 14 bytes del membro sa_data?
questa è il codice che ho scritto:
      struct sockaddr address;
      size_t sizeaddr;
      sizeaddr=sizeof(struct sockaddr);
      connected_socket = accept(listening_socket, &address, &(sizeaddr));
      printf("\ndata=<%s> family=<%d>\n", address.sa_data, address.sa_family);
mi da il seguente output:
data=<&#9830;r
Þ> family=<2>
come lo interpreto?
Grazie per la risposta!


 Gianluca Bove wrote:
Ok, dopo un po' di tentativi ho risolto cosě:
      struct sockaddr address;
      size_t sizeaddr;
      char ipaddress[20];
      int last;
      sizeaddr=sizeof(struct sockaddr);
      connected_socket = accept(listening_socket, &address, &(sizeaddr));
      last=address.sa_data[5];
      if (last < 0) last+=256;
      sprintf(ipaddress, "%d.%d.%d.%d", address.sa_data[2], address.sa_data[3],
                                        address.sa_data[4], last);
      printf("\nipaddress=<%s>\n", ipaddress);
Grazie per l'aiuto, ciao!


       printf("\nipaddress=<%s>\n", ipaddress);
Se noti, anche bind(2) vuole un puntatore ad una struct sockaddr, eppure 
se leggi bene il sorgente che hai postato, vedi che le viene passato un 
puntatore ad una struct sockaddr_in. :-)
Non esiste solo IPv4 a questo mondo (almeno nelle previsioni di chi ha 
progettato l'API dei socket()), e quindi l'API a socket e` stata pensata 
in maniera generica, e prevede di poter manipolare indirizzi 
indipendemente dal tipo di rete sottostante (IPv4, IPv6, socket locali 
in dominio Unix, XNS, etc.).
Questo significa che le chiamate di sistema che hanno a che fare con 
indirizzi manipolano generiche struct sockaddr, le quali sono 
specializzate nelle strutture specifiche in base alla address family del 
socket, ed e` anche per questo che devi passare la lunghezza in byte 
della struttura come parametro, semplicemente perche` le routine come 
accept() manipolano dati generici che poi sono intepretati a seconda del 
valore di sa_family.
La specializzazione di sockaddr per IPv4 (sa_family == AF_INET) e` 
sockaddr_in (in = InterNet).
Per cui, passa come secondo parametro un puntatore ad una struct 
sockaddr_in, castato a struct sockaddr *, e accedi al membro sin_addr 
per recuperare l'indirizzo IP.
