2013-04-27 51 views
-2

對於開發能夠同時處理客戶的最大「X」號的UDP服務器,我有兩個選擇:開銷線程的創建和刪除V/S未使用的線程

  1. 當服務器啓動,如果所有'x'客戶端都處於活動狀態,則立即創建'x'線程而不切入。

  2. 第二個選擇是當服務器啓動時,它等待客戶端的請求,並且當來自特定客戶端的請求到達時,只有一個線程spwaned用於服務該客戶端。 如果特定客戶端關閉,則專用於該特定客戶端的線程也會被刪除。線程

在選項#1,「X」數在開始創建即使僅存在1連接的客戶機中,僅當線程將被使用,並且所有剩餘的「X-1」線將被暫停。

在選項#2中,似乎我將面臨連續線程創建&刪除的開銷。

我決定使用選項#2來執行我的應用程序,但如果我的選擇是正確的,我仍然感到困惑。

如果我錯了,請幫助我。

回答

2

通過實施線程池來組合使用這兩者。創建一個最初爲空的線程池,或者包含大量初始暫停線程,您的選擇。當新客戶端「連接」並且沒有超過允許客戶端的最大數量時,檢查該池是否有可用線程。如果是這樣,請重新使用它。如果沒有,則創建一個新線程。當客戶端「斷開連接」時,將線程放回池中並掛起。如果給定的線程停留在池中一段時間​​,請移除並銷燬它。

1

考慮上下文切換的開銷而線程正在運行。在四核CPU上使用三千個線程會導致比在同一個四核CPU上使用四至八線程更多的開銷。根據堆棧分配,考慮三千個線程將使用的資源與四到八個線程。

在靜態,預定義或用戶可配置數量的線程上處理儘可能多的非阻塞套接字是非常有意義的。

1

選項3 - 可根據需要增加或減少的線程池,或者理想情況下不可用。

1

這是有點困惑你在說什麼,或者,可能需要更多的信息。請記住,UDP客戶端不會連接它們只是發送數據包,並且這些數據包不能保證按照它們發送的順序到達。

我會做的只是有一個偵聽UDP套接字等待數據包。您應該通過其IP地址或任何其他方法(例如數據包數據中的ID)來維護有效客戶端的列表。一旦接收到數據包,您就可以使用處理客戶端請求的函數/線程來處理數據包。正如我所看到的,您甚至不需要啓動新線程,但它取決於接收數據包時服務器將執行的操作以及處理該數據包需要多長時間。此外,請記住,處理請求的函數/線程無法從客戶端接收更多數據包(通過同一端口);所有傳入的數據包都由服務器線程傳遞。處理客戶端請求的函數或線程只需要向客戶端發送一個或多個UDP數據包來確認請求,但它不能與客戶端保持對話,也不能確定客戶端是否因爲沒有永久的開放連接。如果您需要服務器和客戶端之間的對話,則需要更改爲TCP套接字。

這是一個代碼草案:

ClientRequestThread(DatagramPacket packet) 
{ 
    String FromIP = packet.getAddress().getHostAddress(); 
    byte[] data = packet.getData(); 
    // Here you must identify the client, either by its IP address 
    // or maybe an ID inside the data. 

    if (TheDataHaveBeenProccessOK) 
    { 
     Send a positive acknowledge 
    } 
    else 
    { 
     Send a negative acknowledge 
    } 
} 

ServerThread() 
{ 
    DatagramSocket datagramSocket; 
    try 
    { 
     datagramSocket = new DatagramSocket(MyPortNumber); 
    } 
    catch (Exception e) 
    { 
     // Unable to open the datagram socket. 
     // Handle it accordingly 
     return; 
    } 

    byte[] buffer = new byte[256]; // change it to your needs 
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 

    while (YouDontStopMe) 
    { 
     try 
     { 
      datagramSocket.receive(packet); 
// Here you must either call a function or start a thread 
// to handle the client request 
// depends on what you are going to do with the client's request. 
      ClientRequestThread(packet); 
     } 
     catch (Exception e) 
     { 
      // Error reading the socket, handle it accordingly 
      e.printStackTrace(); 
     } 
    } 
    datagramSocket.close(); 
}