2012-03-12 193 views
0

我一直在研究文件下載應用程序,其中服務器連續等待來自客戶端的新連接請求,當新連接到達時服務器接受此連接並創建一個新進程以服務最近連接到服務器的客戶端。客戶端可以請求從服務器下載多個文件。對於每個文件,客戶端和服務器端創建一個新線程,並且每個文件的數據傳輸應在服務器和客戶端的適當線程對之間執行。我使用C和pthread爲線程。現在,我有穩定的套接字連接和成功創建每個客戶端的過程。客戶端 - 服務器應用程序中的線程同步?

對於線程文件transer,我曾嘗試如下:

在客戶端我創建它運行到接收文件的方法線程:

 int k; 
     for (k = 0; k < fNameCounter; k++) 
     { 
      pthread_t thread_id; 
      int status = pthread_create(&thread_id, NULL, &receiveFile, fName); 

      if (status != 0) 
      { 
       printf("Thread Creation Failed \n"); 
       exit(0); 
      } 
     } 

同樣,在服務器端,我創建相同線程數如下:

 int k; 
     for (k = 0; k < fnameCounter; k++) 
     { 
      pthread_t thread_id; 
      int status = pthread_create(&thread_id, NULL, &sendFile, fName); 

      if (status != 0) 
      { 
       printf("Thread Creation Failed \n"); 
       exit(0); 
      } 
     } 

SENDFILE和receiveFile功能簡單的寫入和讀取由FNAME指定的文件的字節(你可以在看在pthread_create )的插座,在這一點上我有一個大問題:

在這個程序中,只要我想,可能有問題,文件的內容可能是從服務器的所有線程完成接收數據後不同,因爲SENDFILE因爲readFile函數只是從套接字讀取並寫入套接字。

我怎麼能保證,客戶的每個線程服務器的正確的線程得到正確的數據,如我解釋如下:

 receive   send 

cthread1 ----> a.txt <----- sthread1 

cthread1 ----> a.txt <----- sthread1 

cthread1 ----> a.txt <----- sthread1 

附:我知道在一個套接字上創建多個線程並不合理,但是,這是我的工作,我需要這樣做:/。

問候。

回答

1

最簡單的方法是爲每個文件打開一個新的套接字。

0

要完成zvrba非常有效的點(一個套接字,一個文件)。

我認爲這裏的線程沒用:你有一張網卡。通過多次收聽同一資源,您不會變得更快。你實際上可能會讓你的線程彼此阻塞,而且實際上會變慢。

如果您想給用戶反饋,那麼您可以爲所有套接字IO創建一個後臺線程。

您應該使用select在同一線程中處理您的多個連接,以檢測哪個套接字可以被讀取/寫入。

+0

實際上,這是一個課程項目,因此我需要這樣做。此外,我知道使用線程是毫無意義的,因爲我將爲每個客戶端提供一個套接字,但我沒有選擇:)並且真的陷入了同步問題。 – StM 2012-03-12 13:26:34

+0

請編輯您的問題以使您的約束更加清晰:使用單個套接字和兩側的多個線程並行發送多個文件。提及這是一項任務,而且這種條件無論如何效率都不可談判。 – 2012-03-12 13:31:40

0

考慮到僅限一個套接字的限制,您可能需要爲正在傳輸的字節添加一些標頭信息。這個頭文件可能包含有關哪一對線程負責那一點信息的信息。

例如,sthread1將從文件a.txt發送100個字節。您可以在該流的開頭添加一個字節,其中包含編號1。當收到該數據塊時,cthread1需要檢查第一個字節:如果它是1那麼ok,這個塊是cthread1,繼續處理。如果標題不是1,那麼cthread1應該忽略這個塊並繼續等待,給其他線程運行的機會。

如果您沒有識別您的數據塊,將無法確定哪個線程應該處理哪個塊。

請注意,這增加了很多複雜的處理:

  1. 你將不得不決定如何將這些標識符分配到雙線程
  2. 如果只使用一個字節,請請注意,它所能容納的最大值爲255.
  3. 您可能必須在函數中使用recv函數中的標誌MSG_PEEK(因此如果需要,您可以忽略該塊)。該標誌改變了功能recv的行爲。我建議你閱讀this(如果你在Win上編程)或this(如果你在Linux上)。