0

次のコードはどのようにできますか

while(1) {
  client_name_len = sizeof(struct sockaddr_in);
  newsockfd = accept(sockfd, (struct sockaddr *)&client_name, &client_name_len);
  if (newsockfd < 0) {
    perror("ERROR on accept");
    printf("Finished\n");
    close(sockfd);
    exit (EXIT_FAILURE);
  }
  printf("a:");
  pthread_t thread1;
  int *addr = (int*)malloc(sizeof(int));
  *addr = newsockfd;
  pthread_create( &thread1, NULL, &ProcessClient, (void*)addr);
}

次の出力を生成します。

a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:ERROR on accept: Too many open files
a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:Finished

問題はperror("ERROR on accept")printf("Finished\n")printf("a:")が同じスレッドで実行されますが、出力が混在していることです。

ProcessClientは何も出力せず、スレッドも作成しません。 sockfd標準のリスニングtcpソケットです。

4

2 に答える 2

2

printf("a:");およびは、printf("Finished\n");stdoutに向かうバッファリングされたI/Oです。

perror("ERROR on accept");バッファリングされていない(またはすぐにフラッシュされる)I/Oがstderrに送信されます。

したがって、a:後に表示される多くのERROR on accept: Too many open filesは、実際にはprintf()前に編集されましたが、バッファリングにより、後でコンソールに表示されます。

問題を解決するための詳細と方法については、https://stackoverflow.com/a/3746795/12711を参照してください。

于 2012-08-18T16:49:28.973 に答える
1

Michaelが指摘したように、最初の問題は、2つの異なるストリーム(stdoutとstderr)を使用していることと、一方がバッファリングされ、もう一方がバッファリングされていないことです。ただし、出力を複数のstdio呼び出しに分割しているため、アトミックではありません。を次のように置き換えることをお勧めperrorします。

printf("ERROR on accept: %s\n", strerror_l(errno));

または、で使用する他のprintf呼び出しを切り替えて、書き込み先のストリームについて一貫性を保つようにします。fprintfstderr

次に、それをアトミックにするためにflockfile(f)、関数の最初で、funlockfile(f)戻る前に呼び出します(ここで、または使用することを選択しfた方に置き換えられます)。または、本当に両方を使用したい場合は、両方をロックすることができます...stdoutstderr

于 2012-08-18T20:05:27.770 に答える