这可能看起来很基本,但由于这是我第一次使用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;
}
答案 0 :(得分:4)
不,它没有。内核复制address
参数的内容;您可以在呼叫返回后立即重用或释放该内存。
实际上,可以在此处做出更一般的声明:除非文档另有说明,否则通过指针引用传递给内核的参数只需要在系统调用期间保持“活动”状态。如果需要,它们的值将由内核复制。
答案 1 :(得分:3)
很安全。 bind()
在返回后不会保留对指针的引用。它只是将其输入作为指针,因为它接收的是一个可变大小的结构,不能通过值传递。 (它本质上是C中的多态性。)