2017-02-04 51 views
0

我有關於併發網絡編程的理論問題。我正在嘗試創建一個客戶端網絡工具,並且我需要它非常快速地執行。該程序將從文本文件中讀取IP地址列表並在其上運行一些功能。這個功能例如:從文本文件中讀取字符串並將它們同時發送到服務器

void conn(char *host, const char *port, char *test_string) 
{ 
    struct addrinfo *res; 
    struct addrinfo hints;  
    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = PF_UNSPEC;  
    hints.ai_socktype = SOCK_STREAM;  
    getaddrinfo(host, port, &hints, &res); 
    int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
    if (s == -1) error("failed to open socket"); 
    int c = connect(s, res->ai_addr, res->ai_addrlen); 
    // send string from file 
    // recv message 
    freeaddrinfo(res);   
} 

我想同時向服務器發送請求以獲得更好的性能,但我不明白我應該如何完全做到這一點。我已經做了研究與POSIX線程的多線程,但我不能拿出的東西,實際上似乎運行異步

while (fgets(buf, sizeof(buf), stringlist)) { 
    if ((c = strchr(buf, '\n')) != NULL) 
     *c = '\0'; 
     strncpy(args.test, buf, 20); 
     pthread_create(&threads, NULL, conn, &args); 
     pthread_join(threads, &res); 
    } 
} 

我意識到,肯定不會以任何方式提高性能,我已經做了進一步的研究,但我開始感到失落。我知道使用fcntl使套接字非阻塞和異步,以及I/O多路複用的選擇功能,但我不知道哪種方法是正確的在這種情況下。

我的問題簡而言之是:什麼是從文本文件中讀取字符串並將包含字符串的併發請求發送到服務器的好方法。多線程適合這種情況嗎?

+3

當你調用'pthread_join'時,程序一直等到線程結束。所以循環創建一個線程,等待它完成,然後讀取下一行。 – user3386109

回答

2

它並沒有真正以並行方式運行:

pthread_create(&threads, NULL, conn, &args); 
pthread_join(threads, &res); 

這裏線程創建做的工作,但主線程在等待它完成。所以只有一個線程在同一時間運行 - 無論是主線程還是工作線程。

要做到這一點並行,有兩種選擇:

  1. 創建並從文件中的每一行啓動線程,並把它放到列表中。最後,等待pthread_join()的所有線程。這可能適用於合理數量的輸入行,因爲通常線程/進程總數有限制。
  2. 創建一個線程池和工作項的隊列。隊列將遵循常見的生產者 - 消費者模式,其中主線程是生產者線程池線程是消費者。消費者線程將在添加到隊列中並處理它時選擇該工作項。

第二種方法好得多,它限制了線程的最大數量,它也可以使底層資源可重用(套接字連接)。

Java對此有很好的抽象,請參閱ExecutorService

對於C你可能沒有太多的選擇,要麼你可以自己實現它。這並不困難 - 一個互斥體可以保護隊列結構和條件來宣告物品的可用性(如果你想限制製作人也可能是另一個互斥體)。或者你可以看看Thread Building BlocksACE這可能會提供線程池,隊列和類似的東西。

+0

由於線程創建發生在fgets循環內部,這並不意味着每個線程在fgets塊之後一次只能處理一個文件條目嗎? – user3408678

+0

@ user348678:是的,有第一個選項。但是線程仍然會並行運行。args參數必須在任何情況下動態分配,因爲下一個fgets會覆蓋現有的解決方案 –

相關問題