【问题标题】:socket and fork with c带 c 的插座和叉子
【发布时间】:2012-09-05 07:35:44
【问题描述】:

这是我的 fork-server 代码:

    signal (SIGINT, ( void *)sig_handler);
while(1){
    memset(&cli_addr, 0, sizeof(cli_addr));

    if((newsockd = accept(sockd, (struct sockaddr *) &cli_addr, (socklen_t *) &socket_len)) < 0){
        perror("Errore nella connessione\n");
        onexit(newsockd, sockd, 0, 2);
    }
    fprintf(stdout, "Ricevuta richiesta di connessione dall' indirizzo %s\n", inet_ntoa(cli_addr.sin_addr));

    child_pid = fork();
    if(child_pid < 0){
        perror("Fork error");
        onexit(newsockd, sockd, 0, 2);
    }
    if(child_pid == 0){
        do_child(newsockd);
    }
    else{
        attended_pid = waitpid(child_pid, NULL, 0);
        if(attended_pid != child_pid){
            printf("Child error");
        }
    }
}

我的问题是:我必须在执行客户端之前关闭主 sock (sockd) 吗?
我认为没有,但是:

  • 我添加了一个“sigint 控制器”,如果我在服务器上按 CTRL-C(带有注释 sockd -> //close(sockd);),sigint 将在 2 个并发连接下执行 3 次(为什么??)李>
  • 如果我有这个代码close(sockd),sigint 将只执行一次,但我在accept 指令上得到一个:bad file descriptor

那么,我该怎么办?
谢谢!

PS:我的签名码:

void sig_handler(const int signo, const int sockd, const int newsockd){
  if (signo == SIGINT){
    printf("Ricevuto SIGINT, esco...\n");
    if(newsockd) close(newsockd);
    if(sockd) close(sockd);
    exit(EXIT_SUCCESS);
  }
}

【问题讨论】:

  • 离题:0 是一个有效的套接字/文件描述符。所以你最好在使用之前和close()ed之后将未使用的套接字/文件描述符初始化为-1,然后使用-1测试它是否有效。
  • 谢谢,我已经更新了我的本地代码 :)
  • 在父进程中,你应该调用例如waitpid 定期为您的孩子打扫卫生。
  • 谢谢 :) 我已经重新更新了我的代码,但是......我有什么要“清理”到父级的??
  • 但是multiple sigint 问题仍然存在:(

标签: c sockets fork


【解决方案1】:

来自fork(2) 手册页:

子级继承父级打开文件描述符集的副本。子文件中的每个文件描述符与父文件中的相应文件描述符引用相同的打开文件描述(请参阅 open(2))。这意味着两个描述符共享打开文件状态标志、当前文件偏移量和信号驱动的 I/O 属性(参见 fcntl(2) 中对 F_SETOWN 和 F_SETSIG 的描述)。

这告诉我你应该关闭子进程中的监听套接字。您也不应该在父进程中关闭已接受的套接字,而应在完成后由子进程将其关闭。

【讨论】:

  • 所以:1)我不必关闭 sockd 对吗? 2)我必须将newsockd关闭到子进程中,所以关闭child_sock是正确的,对吧?
  • @polslinux Yes to number 1. 对于 nubmer 2,newsockd 应该在子级中关闭,但 child_sock 是什么?
  • child_socknewsockd 传递给孩子!我的功能是void do_child(const int child_sockd) :)
  • @polslinux 啊好吧,那你应该在do_child中关闭child_sockd
  • 我已经更新了代码,现在可以了吗? :) PS:我必须添加waitpid ...第二个:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 2013-04-02
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多