【问题标题】:Server socket finishes when client closes connection当客户端关闭连接时服务器套接字完成
【发布时间】:2014-08-04 15:53:16
【问题描述】:

我正在尝试使用 C++ 创建一个服务器套接字,以便一次接受一个客户端连接。该程序成功创建服务器套接字并等待传入​​连接,但是当客户端关闭连接时,程序将无限循环。否则,如果连接中断,它将按预期继续等待新连接。知道为什么会这样吗?谢谢

这是我的 C++ 服务器代码:

   int listenfd, connfd, n;
   struct sockaddr_in servaddr, cliaddr;
   socklen_t clilen;
   pid_t     childpid;
   char mesg[1000];

   listenfd = socket(AF_INET, SOCK_STREAM, 0);

   bzero(&servaddr, sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
   servaddr.sin_port = htons(32000);
   bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

   listen(listenfd, 1024);

    while (true) {
        clilen = sizeof(cliaddr);
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

        if ((childpid = fork()) == 0) {
            close (listenfd);

            while (true) {
                n = recvfrom(connfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
                sendto(connfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));

                mesg[n] = 0;
                printf("%d: %s \n", n, mesg);

                if (n <= 0) break;
            }
            close(connfd);
        }
    }

由于某种原因,当客户端关闭连接时,即使使用if-break 子句,程序也会继续打印-1:..

【问题讨论】:

  • 如果'n'是-1,你应该调用perror(),或者在错误信息中使用strerror[],并且你应该将它用作数组索引测试它。

标签: c++ sockets


【解决方案1】:

您永远不会在父进程中关闭connfd(当 childpid != 0 时),并且您没有正确终止将尝试循环的子进程。您的 if 块应如下所示:

if ((childpid = fork()) == 0) {
    ...
    close(connfd);
    exit(0);
}
else {
    close(connfd);
}

但是正如您所说的一次只接受一个连接,您根本不能分叉。

正如在其他答案中所见:

  • 未经测试请勿使用mesg[n] n >= 0
  • recvfromsendto 对于 TCP 来说太过分了,只需使用 recvsend(甚至是 readwrite

【讨论】:

  • 感谢@Serge,删除了不必要的分叉,在将n 用作mesg 的索引之前对其进行了测试,并使用recvsend 确实解决了问题
【解决方案2】:
mesg[n] = 0;

这在 n

【讨论】:

  • 即使我删除该行,程序仍会循环打印“-1:”,似乎永远不会到达 break 子句..
  • 你确定重复的-1不是来自“新叉子”吗?我建议你在输入 fork 后 printf。顺便说一句,对于现代情况,使用 fork 作为套接字服务器是古老而可怕的,请尝试使用 epoll。
  • 感谢@Calvin,因为 Serge 建议我的场景不需要分叉(但我下次会采纳你的建议)
【解决方案3】:

问题是你的“n”和recvfrom。您有一个 TCP 客户端,因此 recvfrom 不会返回正确的值。

试着看看: How to send and receive data socket TCP (C/C++)

编辑 1:

【讨论】:

    【解决方案4】:

    您已经编写了一个 TCP 服务器,但您使用了专用于无连接协议 (UDP) 的 recvfromsendto

    试试recvsend。也许这可能会有所帮助。

    【讨论】:

    • recvfrom 根据手册页对 tcp 套接字有效(尽管我也使用 recv())
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 2013-01-16
    相关资源
    最近更新 更多