2013-12-16 6 views
5

Ich schreibe ein Programm im Client/Server-Stil. Jetzt entwickle ich die Serverseite, und ich öffne einen Sockel.Wer ist auf Socket in C verbunden

Aber ich muss wissen, wer in meiner Steckdose angeschlossen ist. Welche IP ist verbunden? Weil ich Logs schreiben muss, die sich auf dem Server verbinden.

Also, meine Frage ist, wie kann ich das in C tun? Unter Linux.

Ich versuche getsockopt() zu verwenden, aber nicht funktionieren. Und ich bin neu in der Netzwerkprogrammierung.

Jemand weiß, wie kann ich das tun?

Hier ist der Code meiner Fassung:

int init_socket() { 
    /** Declara um socket */ 
    Socket sock; 

    /** Inicia o socket */ 
    sock.socket = socket(AF_INET, SOCK_STREAM, 0); 

    /** Seta zeros no sockaddr */ 
    memset(&sock.server, 0, sizeof (sock.server)); 

    /** E tambem no buffer */ 
    memset(sock.buff, 0, sizeof (sock.buff)); 

    /** Seta os valores do sockaddr */ 
    sock.server.sin_family = AF_INET; 
    sock.server.sin_addr.s_addr = htonl(INADDR_ANY); 
    //sock.server.sin_port = htons(get_config_int(&conf, "monitor_port")); 
    sock.server.sin_port = htons(2200); 

    /** Chama o bind */ 
    bind(sock.socket, (struct sockaddr*) &sock.server, sizeof (sock.server)); 

    /* 
    * É um socket blocante, então espera encher o buffer 
    * Faz o listen 
    */ 
    if (listen(sock.socket, 2) == -1) { 
     /** Deu falha na preparação para o accept, insere nos logs */ 
     insert_log(FATAL, LOG_KERNEL, "Não foi possível iniciar o socket - event.c"); 

     /** Retorna falha */ 
     return INIT_SOCKET_FAILED; 
    } 

    /** Se chegar aqui, faz o accept, dentro de um loop infinito */ 
    connect: 
    while ((sock.conn = accept(sock.socket, (struct sockaddr*) NULL, NULL))) { 
     printf("Recebi uma conexão, começando comunicação...\n"); 
     /** Agora conn é um file descriptor, podemos ler e gravar nele */ 
     while (1) { 
      if (read(sock.conn, sock.buff, sizeof (sock.buff)) == 0) { 
       close(sock.conn); 
       printf("Pronto para outra conexão...\n"); 
       goto connect; 
      } 
      printf("Eu Li isso do Buffer: %s", sock.buff); 

      /** Limpa o buffer */ 
      memset(sock.buff, 0, sizeof (sock.buff)); 
      sleep(1); 
     } 
    } 

    return INIT_SOCKET_SUCCESS; 
} 

Dank für die Hilfe!

+3

Verwenden Sie 'getpeername()'. –

+0

@ n.m .: Geben Sie stattdessen Ihren Kommentar als Antwort ein. – wilx

Antwort

3

Der accept() Anruf gibt Ihnen die Remote-Adresse, wenn Sie die Adresse ein struct sockaddr als Argument übergeben:

struct sockaddr_storage remoteAddr; 
socklen_t remoteAddrLen = sizeof(remoteAddr); 

sock.conn = accept(sock.socket, (struct sockaddr *)&remoteAddr, &remoteAddrLen); 

Anschließend können Sie die Remote-Adresse in einen String mit getnameinfo konvertieren(), das funktioniert mit beide IPv4 und IPv6:

char host[NI_MAXHOST]; 
getnameinfo((struct sockaddr *)&remoteAddr, remoteAddrLen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); 
1

Ich bin mir nicht sicher, ob ich Ihre Frage richtig verstanden habe. Sie können mit

struct sockaddr_in cli_addr; 

Dann können Sie ein in die Endlosschleife des Server-Code haben

newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen); 

Dann inet_ntoa verwenden() mit cli_addr die IP-Adresse angezeigt werden soll.

0

Sie möchten vielleicht D.J. Bernsteins tcpserver (siehe http://cr.yp.to/ucspi-tcp/tcpserver.html). Im Grunde genommen können Sie Ihr C-Programm einfach unter tcpserver ausführen, und tcpserver behandelt alles, was die Einrichtung der Sockets, die Auflistung eingehender Verbindungen auf dem von Ihnen verwendeten Port usw. betrifft. Wenn eine eingehende Verbindung an dem von Ihnen angegebenen Port eintrifft, tcpserver erstellt eine Instanz Ihres Programms und leitet eingehende Informationen vom Client an die STDIN Ihres Programms und leitet ausgehende Informationen aus dem STDOUT Ihres Programms zurück an den Client. Auf diese Weise können Sie sich auf die Kernlogik Ihres Programms konzentrieren (und einfach auf stdout/stdin lesen/schreiben), und tcpserver kann das gesamte Heavy Lifting bis zu den Sockeln usw. bewältigen. Um die IP-Adresse des Clients zu erhalten, lesen Sie einfach die $ TCPREMOTEIP Umgebungsvariable.