2013-12-16 8 views
5

私はクライアント/サーバースタイルのプログラムを書いています。今私はサーバー側を開発しています。私はソケットを開きます。Cでソケットに接続する人

しかし、私は誰が私のソケットに接続されているか知る必要があります。どのIPが接続されているか。私はサーバに接続するログを入れる必要があるからです。

だから、私の質問はどのようにCでこれを行うことができますか? Linuxを使う。

getsockopt()を使用しようとしましたが動作しません。そして、私はネットワークプログラミングの新人です。

誰かがこれを行う方法を知っていますか?ここで

は私のソケットのコードは次のとおりです。助けを

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; 
} 

ありがとう!

+3

'getpeername()'を使用してください。 –

+0

@ n.m .:あなたのコメントを答えてください。 – wilx

答えて

3

あなたは引数としてアドレスstruct sockaddrの を渡す場合accept()コールはあなたにリモートアドレスを与える:

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

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

あなたが、その後はgetnameinfo(の文字列へのリモートアドレスを変換することができます)、 これはで動作しますIPv4とIPv6の両方:

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

あなたの質問が正しいかどうかはわかりません。あなたは、あなたがcli_addrを使用してIPアドレスを表示するには、()INET_NTOAを使用すると、サーバーコードの無限ループで

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

を持つことができます

struct sockaddr_in cli_addr; 

を使用することができます。

0

D.J. Bernsteinのtcpserver(http://cr.yp.to/ucspi-tcp/tcpserver.htmlを参照)。基本的には、tcpserverの下でCプログラムを実行するだけで、tcpserverはソケットの設定、使用しているポートの着信接続のリスト表示などすべてを処理します。着信接続が指定したポートに到着すると、 tcpserverはプログラムのインスタンスを生成し、クライアントから受信した情報をプログラムのSTDINにパイプし、プログラムのSTDOUTから送信する情報をクライアントにパイプします。こうすることで、プログラムのコアロジック(stdout/stdinへの読み書き)に集中し、tcpserverがソケットなどの重い荷物をすべて処理できるようにすることができます。クライアントのIPアドレスを取得するには、 $ TCPREMOTEIP環境変数。