【问题标题】:Who is connect on Socket in C谁在 C 中的 Socket 上连接
【发布时间】:2013-12-17 11:54:08
【问题描述】:

我正在编写一些客户端/服务器风格的程序。现在我正在开发服务器端,并打开一个套接字。

但是,我需要知道我的套接字中连接了谁。连接什么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;
}

感谢您的帮助!

【问题讨论】:

  • @n.m.:让您的评论成为答案。

标签: c linux sockets


【解决方案1】:

如果您传递地址,accept() 调用会为您提供远程地址 struct sockaddr 作为参数:

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

【讨论】:

    【解决方案2】:

    我不确定我的问题是否正确。你可以使用

    struct sockaddr_in cli_addr;
    

    那么你就可以在服务端代码无限循环了

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

    然后使用inet_ntoa()通过cli_addr显示IP地址。

    【讨论】:

      【解决方案3】:

      您可能想看看 D.J. Bernstein 的 tcpserver(参见 http://cr.yp.to/ucspi-tcp/tcpserver.html)。基本上,您可以简单地在 tcpserver 下运行您的 C 程序,tcpserver 将处理所有事情,包括设置套接字、列出您正在使用的任何端口上的传入连接等。当传入连接到达您指定的端口时, tcpserver 将生成程序的一个实例,并将来自客户端的传入信息通过管道传输到程序的 STDIN,并将来自程序的 STDOUT 的传出信息传输回客户端。这样,您可以专注于程序的核心逻辑(并简单地读/写到 stdout/stdin),并让 tcpserver 处理所有繁重的工作,如套接字等。要获取客户端的 IP 地址,只需读取$TCPREMOTEIP 环境变量。

      【讨论】:

        【解决方案4】:

        我想你可以试试 getpeername(2) 和 inet_ntoa(3)。 http://linux.die.net/man/2/getpeername, http://linux.die.net/man/3/inet_ntoa

        【讨论】:

          猜你喜欢
          • 2017-09-02
          • 2020-06-12
          • 1970-01-01
          • 2015-02-01
          • 2019-03-26
          • 1970-01-01
          • 2014-02-15
          • 2014-02-26
          • 2011-07-31
          相关资源
          最近更新 更多