为什么这个自定义网络服务崩溃(用C语言编写)?

时间:2012-10-20 14:01:42

标签: c debugging network-programming

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

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;
}

2 个答案:

答案 0 :(得分:2)

  

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

虽然这段代码可以提高效率(例如通过在一次传递中写入所有字节),但那里没有明显的缺陷。

这使得代码中未发布的部分成为问题的理想选择:

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

如果您读取的字节数超过y[]的大小,则会崩溃。

  

或(或者)如果有人可以建议一种方法使其更健壮

尝试扩大此y[]缓冲区的大小(加倍可以不受伤害)。

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

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

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

答案 1 :(得分:1)

代码看起来很好用一些评论。 一个有点重要的评论: portno应声明为unsigned short。对于类似英特尔(小端)的处理器,它可以正常工作,但它不能移植到具有不同字节序的处理器。

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

显然,在'while'内执行时会发生崩溃,并且通过查看代码,如果崩溃导致缓冲区溢出,唯一的可能就是fill_buffer。

如果您显示BYTES和fill_buffer的定义,那么将更容易为您提供帮助。

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

你也可以忽略SIGPIPE:

signal(SIGPIPE, SIG_IGN);

其他可能性是,如果你正在使用write_val做一些奇怪的事情而你没有显示该代码。

我希望这会有所帮助。