0

特定のポートでリッスンし、接続が受信されると、1行のテキストを出力して切断するこのプログラムを作成しました。数日間実行され、数千のクエリを処理しますが、その後 (必然的に) クラッシュし、再起動する必要があります。誰かがそれで何か問題があると思うか、または(代わりに)誰かがそれをより堅牢にする方法を提案できるかどうか疑問に思っています.

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

誰もがそれで何か悪いことを見ます

このコードは (たとえば、1 回のパスですべてのバイトを書き込むことによって) より効率的にすることができますが、明らかな欠陥はありません。

これにより、コードの未公開部分が問題の適切な候補になります。

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

のサイズよりも多くのバイトを読み取るy[]と、クラッシュします。

または(代わりに)誰かがそれをより堅牢にする方法を提案できる場合

このバッファのサイズを大きくしてみてくださいy[](2 倍にしても問題ありません)。

文字fill_buffer()を超える読み取りができないことを確認してください。BYTES

疑わしい場合は、この不足しているコードを公開してください。

また、デバッグ シンボルを使用してコードをコンパイルし、シグナル ハンドラからファイルに (シンボルを使用して) バックトレースをダンプすることもできます。このようにして、プログラムがクラッシュした場合にwherewhy.

于 2012-10-20T15:41:42.957 に答える
1

コードはいくつかのコメントで見栄えがします。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 に答える