2012-11-04 41 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實際上把'fflush(stdout)'放在'printf(「正在等待一個連接\ n」)的上方和下方;'但仍然輸出相同 – quartaela

回答

2

沒有問題。除了第一次輸入循環之外,「等待連接」將是客戶端連接後由接受線程輸出的最後一件事情。換句話說,除了第一次輸入外,此循環開始/結束於accept()調用。這是第一次通過這是'例外',而不是後來的循環。

+0

是的,最後我意識到命令是真實的。我的錯:) :) – quartaela

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

關閉輸出緩衝。 printf是不可重入,所以它使用全局鎖進行同步。 當緩衝輸出時,一個線程在另一個線程開始打印之前可能不會釋放其鎖。

它始終是最好turn off output buffering或手動調用fflush(),多線程

+0

我試着在'printf'語句的上面和下面調用'fflush(stdout)'。但他們都沒有工作 – quartaela

+0

..因爲沒有什麼可以解決的! –

0

時,如果你使用的混合標準錯誤和標準輸出的,你不能指望,除非你每次使用後沖水正確排序。事情變得更復雜,多線程(沖洗不會足夠),所以我認爲你應該選擇一個流(stdout或stderr)並堅持下去。

+0

有沒有一種方法可以正確使用它們?或者只使用其中之一是避免任何複雜因素的唯一方法 – quartaela

+0

如果您想在兩者都可能引用相同的底層文件或終端時混合使用它們,則會得到損壞的輸出(可能隨機交錯)。避免這種情況的唯一方法是創建自己的互斥鎖來保護標準輸出和標準錯誤,並在每次寫入任何一個時鎖定它。 –

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 

如果您改變而循環咯,輸出將成爲自我記錄:

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(或「我更有用」值)的小結構。

+0

最後 - 別人得到它!我以爲這是我瘋了:) –

+0

對不起,我沒有注意到,並瘋了。謝謝你的揭示回覆:) – quartaela

+2

@quartaela - 不需要aplologise。由於阻塞呼叫而停在中間的循環只是那些多線程的東西之一,你會習慣後會有點:) –