C中的网络; bind()需要它的参数是否存活?

时间:2015-04-30 21:28:12

标签: c linux sockets

这可能看起来很基本,但由于这是我第一次使用C语言进行网络化,我想确保我没有做任何愚蠢的事情,所以我认为...比运行某些未定义更安全,一路上的奇怪行为。
请考虑以下用于在C中设置服务器套接字的代码:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>


int main(int argc, char* argv[]) {

    int listenfd, connfd;
    struct sockaddr_in serv_addr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    // setting 'serv_addr'
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(5000);

    bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));

    if (listen(listenfd, 10) == -1) {
        printf("Failed to listen\n");
        return -1;
    }



    while(1) {
        connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL);

        // do some writing/reading with connfd...

        close(connfd);
    }

    return 0;
}

请注意bind()函数以&struct sockaddr_in为参数 根据{{​​3}}:

  

bind()指定          addr指定的地址由文件引用的套接字          描述符sockfd。

现在假设在执行while循环期间,我再次对此serv_addr引用显式引用。
套接字是否需要struct sockaddr_in,或bind()返回后,是否不再需要struct sockaddr_in了?
套接字是否以某种方式进行了隐式引用?

更准确地说,以下代码是否安全?

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>


int some_other_function() {

    int listenfd;
    /* struct sockaddr_in is defined locally in some_other_function()*/
    struct sockaddr_in serv_addr;


    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    // setting 'serv_addr'
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(5000);

    bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));

    if (listen(listenfd, 10) == -1) {
        printf("Failed to listen\n");
        return -1;
    }

    return listenfd;
}   /* if the socket will refer to &serv_addr from now on, it'll dereference a dangling pointer */



int main(int argc, char* argv[]) {

    int listenfd=some_other_function();
    int connfd;

    while(1) {

        /** is sockaddr_in serv_addr being referenced here? is it needed by accept()? **/

        connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL);

        // do some writing/reading with connfd...

        close(connfd);
    }

    return 0;
}

2 个答案:

答案 0 :(得分:4)

不,它没有。内核复制address参数的内容;您可以在呼叫返回后立即重用或释放该内存。

实际上,可以在此处做出更一般的声明:除非文档另有说明,否则通过指针引用传递给内核的参数只需要在系统调用期间保持“活动”状态。如果需要,它们的值将由内核复制。

答案 1 :(得分:3)

很安全。 bind()在返回后不会保留对指针的引用。它只是将其输入作为指针,因为它接收的是一个可变大小的结构,不能通过值传递。 (它本质上是C中的多态性。)