0

我编写了这个程序,它在给定端口上侦听,然后,一旦收到连接,就会输出一行文本并断开连接。它运行了好几天,处理了数千个查询,但随后(不可避免地)崩溃了,我不得不重新启动它。想知道是否有人认为它有任何问题,或者(或者)是否有人可以提出一种使其更健壮的方法。

int main(int argc, char *argv[])
{
     srand(time(0));

     int sockfd, newsockfd, portno;
     socklen_t clilen;
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);

   while (1)
   {
     unsigned char write_val;
     unsigned char y[BYTES];
     int i, j;

     newsockfd = accept(sockfd,
                 (struct sockaddr *) &cli_addr,
                 &clilen);
     if (newsockfd < 0)
          error("ERROR on accept");

     fill_buffer(y);  // fills buffer y with a 128-bit string; not included here
     for (i=BYTES-1; i >= 0; i--)
     {
       const void* ZERO = (void *)"0";
       const void* ONE  = (void *)"1";

       for (j=7; j >= 0; j--)
         write(newsockfd, (y[i] >> j) & 1 ? ONE : ZERO, 1);
     }

     write(newsockfd, "\n", 1);
     close(newsockfd);
   }

   close(sockfd);
   return 0;
}
4

2 回答 2

2

任何人都认为它有任何问题

虽然这段代码可以变得更高效(例如通过一次写入所有字节),但那里没有明显的缺陷。

这使得您的代码中未发布的部分成为该问题的合适候选者:

fill_buffer(y);  // fills buffer y with a 128-bit string; not included here

如果您读取的字节数超过y[]'s 的大小,那么您将崩溃。

或者(或者)如果有人可以提出一种让它更健壮的方法

尝试扩大这个y[]缓冲区的大小(加倍不会有坏处)。

并确保fill_buffer()不能读取超过BYTES字符。

如有疑问,请发布此缺失的代码。

您还可以使用调试符号编译代码并将回溯(带有符号)从信号处理程序转储到文件中。这样,如果你的程序崩溃了,你就会知道wherewhy.

于 2012-10-20T15:41:42.957 回答
1

带有一些注释的代码看起来不错。一个有点重要的评论:portno 应该被声明为 unsigned short。这适用于类似 Intel(小端)的处理器,但它不能移植到具有不同端序的处理器。

无论如何,这不是您的进程崩溃的原因。

显然崩溃是在“while”内执行时发生的,通过查看代码,如果它因缓冲区溢出而崩溃,唯一的可能性是在 fill_buffer 内。

如果您显示 BYTES 和 fill_buffer 的定义,它将更容易帮助您。

现在,如果它不是缓冲区溢出,那么如果客户端在服务器写入套接字之前关闭连接,它就有可能在写入中中止。在这种情况下,进程将收到信号 SIGPIPE,如果代码不处理该信号,它将中止。

您还可以使用以下命令忽略 SIGPIPE:

signal(SIGPIPE, SIG_IGN);

另一种可能性是,如果您使用 write_val 做了一些奇怪的事情并且您没有显示该代码。

我希望这有帮助。

于 2014-01-02T15:12:23.367 回答