2012-11-04 3 views
1

안녕하세요. 스레드를 사용하는 동안 printf에 약간의 문제가 있습니다. 문제는 터미널이 이전에 인쇄해야하는 printf 문을 약간 나중에 출력한다는 것입니다. 이것이 제가이 문제에 직면 해있는 부분입니다.스레드를 사용하는 동안 printf가 제대로 작동하지 않습니다.

. 
. 
. 
     while(1){ 

     printf("waiting for a connection\n"); 

     csock = (int*)malloc(sizeof(int)); 

     if((*csock = accept(hsock, (struct sockaddr*)&sadr, &addr_size))!= -1){ 
      printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr)); 
      client_counter++; 
      pthread_create(&thread_id,0,&SocketHandler, (void*)csock); 
     } 

     else{ 
      fprintf(stderr, "Error accepting %d\n", errno); 
     } 
     }// end while 
. 
. 
. 

이것은 스레드의 사용 기능입니다.

void* SocketHandler(void* lp){ 

    int *csock = (int*)lp; 
    char buffer[1024]; 
    int buffer_len = 1024; 
    int bytecount; 
    char* str_exit="exit"; 

     while(1){ 

      memset(buffer, 0, buffer_len); 

      if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){ 
      fprintf(stderr, "Error receiving data %d\n", errno); 
      exit(0); 
      } 

      if(strcmp(buffer,str_exit)==0){ 
       break; 
      } 

      printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 
      strcat(buffer, " SERVER ECHO"); 

      if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){ 
      fprintf(stderr, "Error sending data %d\n", errno); 
      exit(0); 
      } 

       //printf("Sent bytes %d Sent String %s\n", bytecount,buffer); 
     } 

    printf("Client disconnected\n"); 
    free(csock); 
    return 0; 
} 

그리고 출력은 클라이언트 (스레드)가 서버에 연결할 때마다 이와 유사합니다. 첫 번째 클라이언트가 출력을 연결

waiting for a connection 
--------------------- 
Received connection from 127.0.0.1 
waiting for a connection 
Client disconnected 
--------------------- 
Received connection from 127.0.0.1 
waiting for a connection 
Client disconnected 

이 제대로 작동하지만 두 번째 문자열을 연결할 때 "waiting for a connection""Received connection" 후에 온다. 잘 대조되는 방식으로 작동해야합니다. 어쨌든

+1

아마도'fflush()'에 대해서 생각할 필요가있을 것입니다. ['flockfile()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html)과'funlockfile()'에 대해서 생각할 필요가 있습니다. –

+2

문제는 어디에서 발생합니까 - 대기/수신, 대기/수신, 대기 중입니다. 그것이 당신이 코딩 한 방법이며 기대했던 결과물입니다. 수락 스레드는 시작하고 대기 한 다음 두 개의 연결을 수신 한 다음 다른 연결을 기다립니다. –

+0

@JonathanLeffler는'printf (연결 대기 중 \ n "); '의 위와 아래에서'fflush (stdout)'을 실제로 넣었지만 여전히 출력은 동일했습니다 – quartaela

답변

2

문제는 없습니다. 루프가 처음 입력 된 것 외에도 '연결 대기 중'은 클라이언트 연결 후 수락 스레드가 인쇄 한 마지막 것입니다.

다른 말로하면,이 루프는 처음 입력 한 경우를 제외하고는 accept() 호출에서 시작/종료됩니다. 그것은 처음부터 끝내는 루프가 아니라 '예외'입니다.

+0

네, 마침내 나는 그 명령이 사실임을 깨달았다. 내 잘못 :) – quartaela

1
setbuf(stdout,NULL); 
setbuf(stderr,NULL); 

출력 버퍼링를 끄고 도움을 감사 할 수 있다면 다행 일 것이다. printf는이 아니므로 글로벌 잠금을 사용하여 동기화됩니다. 출력을 버퍼링 할 때 다른 스레드가 인쇄를 시작하기 전에 한 스레드가 잠금을 해제하지 못할 수 있습니다.

그것은 turn off output buffering 항상 좋습니다 또는 표준 에러와 표준 출력의 사용을 혼합하는 경우

+0

'printf' 문의 위와 아래에 정확히'fflush (stdout)'을 호출 해 보았습니다. 그러나 그들 중 누구도 – quartaela

+0

을 해결하지 못했습니다. 왜냐하면 고칠 것이 없기 때문입니다! –

0

멀티 스레딩 때, 수동으로 fflush()를 호출하면 않는 한 당신은 세척 사용 후 적절한 순서를 기대할 수 없다. 여러 스레드에서 상황이 더욱 복잡해 지므로 (플러시가 충분하지 않을 수 있습니다), 하나의 스트림 (stdout 또는 stderr)을 선택해야합니다.

+0

두 가지 방법을 올바르게 사용할 수있는 방법은 무엇입니까? 그 중 하나만 사용하면 어떤 복잡한 문제도 해결할 수있는 유일한 방법입니다. – quartaela

+0

두 파일을 동일한 기본 파일이나 터미널을 참조 할 때 사용할 수있는 경우 출력이 손상됩니다 (임의로 인터리브 될 수 있음). 이를 방지하는 유일한 방법은 stdout과 stderr를 모두 보호하는 자체 뮤텍스를 생성하고 둘 중 하나에 쓸 때마다 잠그는 것입니다. –

1

문제가 없습니다 (또는 적어도 문제가 아니라고 설명하는 것이 좋습니다). 여기에 몇 가지 주석 출력입니다 :

waiting for a connection    # 1 
---------------------    # 1 
Received connection from 127.0.0.1 # 1 
waiting for a connection    # 2 
Client disconnected     #  thread handling connection 1 
---------------------    # 2 
Received connection from 127.0.0.1 # 2 
waiting for a connection    #  3 
Client disconnected     #  thread handling connection 2 

당신이 약간 while 루프를 변경하는 경우, 출력은 자체 문서화 될 것입니다 :

int i = 0; 
while(1) { 

    printf("%d: waiting for a connection\n", i); 

    csock = (int*)malloc(sizeof(int)); 

    if((*csock = accept(hsock, (struct sockaddr*)&sadr, &addr_size))!= -1) { 
     printf("%d: ---------------------\n%d: Received connection from %s\n", 
      i, i, inet_ntoa(sadr.sin_addr)); 
     client_counter++; 
     pthread_create(&thread_id,0,&SocketHandler, (void*)csock); 
    } 

    else{ 
     fprintf(stderr, "%d: Error accepting %d\n", i, errno); 
    } 

    ++i; 
}// end while 

당신은 인쇄 할 스레드에 대한 유사한 ID를 추가 할 수 있습니다 -에 대한 예를 들어, 소켓을 나타내는 하나의 int을 전달하는 대신, 소켓이 들어있는 작은 구조체와 스레드가 생성되었을 때 client_counter (또는 i 또는 더 유용한 것) 값을 전달하십시오.

+0

마침내 - 다른 사람이 그것을 얻을! 나는 그것이 미쳤다라고 생각했다 :) –

+0

미안 소년 나는주의를 기울이지 않고 있었고, 미쳤다. 공개 답변을 주셔서 감사합니다 :) – quartaela

+2

@ quartaela - 필요가 없습니다. 블로킹 호출로 인해 중간에 멈추는 루프는 멀티 스레딩 작업 중 하나입니다. –

관련 문제