2009-12-24 94 views
4

由於有多種連接多客戶端到服務器的方式,例如:fork,select,threads等。如果能描述哪個更好地將多個客戶端連接到服務器,我會很高興。將多個客戶端連接到服務器的好方法是什麼?

+3

你能更具體嗎? – Andres 2009-12-24 13:45:21

+0

謝謝!再次看到問題,我修改了它... – make 2009-12-24 14:12:50

回答

6

查看C10K頁面,瞭解I/O框架和策略的概述和比較。

+0

感謝您的鏈接。這很有趣 – make 2009-12-24 15:25:04

+0

優秀的網頁! – 2009-12-24 18:54:23

4

設計一些心跳循環,它會遍歷所有的套接字並響應它們各自的事件。

我推薦服務器是被動的(客戶端將連接到它,而不是服務器連接到客戶端),因爲它通常在網絡上完成。因此,它也會有一個監聽套接字。

+1

心跳循環是一個壞主意。因爲它意味着支票之間的強迫睡眠(也許你有其他的想法,在這種情況下忽略這一點)。已經有一個API等待一組套接字上的數據。看看'http://linux.die.net/man/2/select' – 2009-12-24 18:17:00

+0

和Linux上的epoll,BSDs/MacOSX上的kqueue等等:) :) – 2009-12-24 19:47:26

+0

@martin,你等一組套接字,但是你查看所有列表並查看獲得的事件。 – 2009-12-24 19:58:13

1

我知道在C中fd_select提供了這種輪詢套接字的能力。不確定,但我猜測C#有更好的方法來做到這一點。

+0

謝謝!你能解釋一下你的意思是什麼?「輪詢插座的能力.. – make 2009-12-24 15:26:51

2

一個簡單的建議,避免使用fork,因爲它會創建一個重量級的進程,使用線程而不是輕得多,並共享當時創建的進程的相同內存空間。

+0

這取決於操作系統。在UNIX上,fork()和進程是有效的。線程之間共享的地址空間也會導致很難產生錯誤。總之,流程和線程都有優點和缺點。 – 2009-12-24 14:13:17

+0

謝謝!我知道fork()在Windows上不受支持 – make 2009-12-24 21:53:02

2

至少有兩個選項。

  • 創建一個監聽套接字。
  • 等待連接。
  • 產生一個線程來處理連接。

  • 創建一個監聽套接字,並等待它使用select()。
  • 如果偵聽套接字fd變爲活動狀態,則建立新的連接並將新的fd添加到選擇呼叫。
  • 如果連接fd變爲活動狀態,則處理它。

如果你瞭解線程,第一個選擇可能是一個更清潔的方法。第二種方法需要一些fd管理(例如監聽或連接),但可以在單個線程中完成。

what do you mean by this <<the first alternative might be a cleaner approach>>? can you explain pls? 

如果你理解了線程和線程之間的同步,第一種方法可以更簡單,因爲你可以使用正常封閉讀取和寫入連接插座。

第二種方法要求您使用非阻塞讀/寫和處理部分數據包,如果你想能夠同時處理所有的客戶端。

+0

我理解線程並在不同的操作系統上使用它們。對不起,我認爲你已經不在話題了......問題不是關於套接字,而是關於將多個客戶端連接到服務器 – make 2009-12-24 14:08:57

+0

對不起,我沒有把自己弄清楚。我正在描述兩種方式讓服務器處理多個客戶端。我過去都用過它們。 – 2009-12-24 14:11:13

+0

這是什麼意思?「第一種選擇可能是更清潔的方法」?你能解釋一下嗎? – make 2009-12-24 14:20:32

1

如果您的程序在Windows上運行。完全避免線程和進程,並使用套接字編程的異步模型。這是迄今爲止進行網絡通信最有效(最簡單的方法)。

+0

謝謝!你能否解釋一下如何在Windows上使用異步套接字以及爲什麼線程無用...... – make 2009-12-24 21:55:43

1

如果您使用的是Windows,那麼處理大量客戶端的最有效方法是圍繞異步I/O和I/O完成端口構建服務器。這些允許您以有效的方式爲少量(4?)線程服務大量(10萬)客戶端。

有些人認爲I/O完成端口模型的異步性質有點難以理解,但我有一個免費的C++源代碼框架,您可以從here下載以幫助您入門。如果您使用的是託管代碼,那麼.Net框架中的所有異步套接字API都會在「引擎蓋下」使用I/O完成端口。

I/O完成端口模型可以很好地擴展,因爲它是一個從零開始建立起來的高效操作系統原語;它知道與它關聯的線程是否正在運行或等待,因此可以管理它允許同時處理「完成」的線程數量。它也按照fifo順序使用線程,因此如果沒有什麼工作要做,那麼浪費的上下文切換就會減少,因爲只有最小線程數將被使用(而不是跨所有線程調度工作項並導致所有線程堆棧保持分頁到內存中)。相比之下,您自己的線程池必須效率較低,因爲您不具有與IOCP相同的線程知識水平。選擇經常受限於它可以支持的套接字數量,這意味着爲了獲得真正的可伸縮性,您需要在選擇的頂部構建一些複雜的代碼,以便能夠管理超過此數量的客戶端。對每個連接模型使用線程的效率低得多,因爲不僅新線程定期啓動和停止,而且您在任何時候都不能控制進程中的線程數 - 當您將因素分配給線程時,線程是相對重的資源在他們的堆棧空間等等。一旦你有更多的線程比CPU核心,你將失去在上下文切換(IOCP通常完全避免)的時間。最後,爲每個連接分配一個新進程的權重比每個連接模型的線程更重,我個人也沒有看到任何理由認爲這是現代操作系統的有效選項。

+0

非常感謝回覆 – make 2009-12-24 22:33:28

相關問題