Web項目經常須要將數據儘量快地推送給客戶,必要時無需等待客戶端請求。對於與用戶之間進行實時通訊的網站,例如在線交流或文檔協做工具,或者在長期運行的計算/執行任務的服務器上更新系統狀態,等等這些時候,採用雙向溝通機制是理想的。 之前,這類問題通常使用下面的解決方案: • 使用 Flash 中的 Socket 鏈接(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html) • Ajax 長輪詢(https://gist.github.com/jasdeepkhalsa/4353139) • 服務器發送事件... (http://en.wikipedia.org/wiki/Server-sent_events) • ...或者就用 IE 中經典的 Frame 技術(http://cometdaily.com/2007/11/05/the-forever-frame-technique/) 但如今咱們有了更好的選擇:WebSocket。它的標準在2011年發佈,在現代瀏覽器上已實施了一段時間。它更好的緣由是使用更安全和更成熟的協議,帶來了改進和升級。 略注: 這份比較是幾個月前作的,可能不夠及時,但若是有人要找好的WebSocket庫,我認爲這對他仍然是有用的。 本比較只針對以 NuGet 包形式發佈的庫, SuperWebSocket 雖然使用 NuGet 的 repository,但須要從網頁中下載。 也許等我抽出空來,我會使用新的庫或已測試的庫的新版本進行比較而後更新這篇文章。 Fleck https://github.com/statianzo/Fleck 我發現這個庫真的是簡單易用,對於庫、文檔、例子等都是,只要添加庫,複製幾行例子裏的代碼,而後運行——就這麼簡單。 可是簡單是有代價的:其功能並不強大,且可配置的地方太少。 1 2 3 4 5 6 7 8 9 10 private static void Main(string[] args) { var server = new WebSocketServer("ws://localhost:8181"); server.Start(socket => { socket.OnOpen = () => OnOpen(socket); socket.OnClose = () => OnClose(socket); socket.OnMessage = m => OnMessage(socket, m); }); } 對於簡單快速的項目我會用它,若是你不須要用WebSocket發送太複雜的數據結構、命令同樣的消息、或在客戶端無WebSocket支持時的備選方式,這就是你要的了。 優勢: • 簡單 • 無依賴項 缺點: • 可配置項少 • 客戶端瀏覽器不支持WebSocket時就沒戲了 SignalR http://www.asp.net/signalr 微軟出品是我認爲這個庫最大的優勢了。它已經和現有的ASP.NET框架作了集成,對服務器端和客戶端代碼都作了很好的抽象類, 這意味着你不須要太深刻了解協議的東西。而後它還能夠很聰明地在客戶端瀏覽器不支持WebSocket時自動使用別的通訊機制。它還能夠完成一些叫遠程過程調用(RPC)的東西,從服務器到客戶端。 它能廣播消息到全部客戶端,也能單獨發給指定用戶。對大量併發鏈接的處理也很優秀。還有——它是開源的! 聽起來很棒是不?可是...它須要IIS8或者說Windows Server 2012(Windows8也行,不過相信你不會在win8上面跑大項目的)。對我來講,這就是「微軟新一代值得買的操做系統」的超酷特性。若是開發企業項目的話是不錯的,但對小項目來講,爲了這個開源的庫買操做系統——太貴了。 固然這些環境是WebSocket必需要求的. 這篇文章就是講WebSocket通信的,因此我把這個算成大缺點。 1 2 3 4 5 6 7 8 public class MyHub1 : Hub { public void Send(string name, string message) { // Call the broadcastMessage method to update clients. Clients.All.broadcastMessage(name, message); } } 1 2 3 4 5 6 7 8 9 10 11 $(function () { var chat = $.connection.myHub1; chat.client.broadcastMessage = function (name, message) { //... }; $.connection.hub.start().done(function () { $('#sendmessage').click(function () { chat.server.send('message'); }); }); }); 優勢: • 很是好的抽象 • 與IIS和ASP.NET緊密集成 • 不少候選方式 • 開源 • 微軟官方庫 • 可擴展性好 缺點: • 須要IIS8… • … 也就是Windows Server 2012太貴了 AlchemyWebSocket http://alchemywebsockets.net/ 當我想到websocket庫時,這個讓人難以想象。沒錯這是真的。它能夠排在Fleck後面,它很是容易使用,容易安裝(Nuget包可用),文檔中含有很好的例子。 它包含服務端和客戶端兩部分,同時也具備可伸縮性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 static void Main(string[] args) { // 建立一個新的server - 接受端口和ip範圍, // 設置方法 var aServer = new WebSocketServer(81, IPAddress.Any) { OnReceive = OnReceive, OnSend = OnSend, OnConnect = OnConnect, OnConnected = OnConnected, OnDisconnect = OnDisconnect, TimeOut = new TimeSpan(0, 5, 0) }; aServer.Start(); string consoleReadLine; do { consoleReadLine = Console.ReadLine(); sockets.ForEach(s => s.Send(consoleReadLine)); } while (consoleReadLine != "exit"); } 可是它有一些彆扭,我不能避開。例如那裏沒有簡單的事件方法"OnReceive",僅僅只有string,事實上消息在客戶端被髮送了。你必須你本身完成。是的,你必須調用,並且只能調用 .ToString()來獲得真實的消息,但使用庫的目的是爲了避免要強迫本身實現通訊協議。 1 2 3 4 private static void OnReceive(UserContext context) { Console.WriteLine("Client " + context.ClientAddress.ToString() + " sended: " + context.DataFrame.ToString()); } WebSocket服務器初始化方法首先接收端口而後是IP設置。我一直認爲,地址的表達應該是先IP而後是端口,並且只有當有必要指明端口的時候。還有超時設置:爲何必須有超時呢?我能夠理解這有時多是有用的,但它做爲一個特性不該做爲主要設置之一。固然,這只是一些細節問題。 對我來講這迫使你一開始就得經過這個庫用另外一層代碼把它抽象出來。 總之你能夠試試,和Fleck比較一下性能,而後決定哪一個更適合你的簡單項目。 優點: • 簡單 • 無依賴性 • 文檔完備 缺點: • 有點笨拙,比Fleck結構更復雜 • 沒有 fallback XSockets http://xsockets.net/ 這個庫看上去頗有前途。我嘗試過它,而且還花了不少時間,用它工做超過其它的庫(甚至用來執行測試工做等等)。可是很不幸我沒有運氣,任何我考慮到的錯誤在這個庫中都是錯誤的,與代碼不一致的糟糕文檔。難道是由於代碼或者文檔過時了?它不容易安裝和運行,事實上這個庫的使用樣例我很難組建和運行。Xsocket更多向咱們展現了MVC框架的樣子。我嘗試把它運行在ASP.NET項目裏面,MVC和WinService,遺憾的是沒有一個可以工做。 我真的很想用這個庫,但最後我放棄了以便支持更好的庫(閱讀其餘)。認真地說爲何使用這個庫是困難的,甚至一個簡單的項目。你能夠預測更多的問題當把它使用在項目裏,我強烈建議避開這個項目。 1 2 3 4 5 6 7 8 9 public static class XSocketsBootstrap { private static IXBaseServerContainer wss; public static void Start() { wss = XSockets.Plugin.Framework.Composable.GetExport(); wss.StartServers(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33html
Advantages:git
Disadvantages:github
http://msdn.microsoft.com/en-us/hh969243.aspxweb
Another library from Microsoft. And it requires IIS 8 too, so I did not have means to test it. Examples are really low level, so it force you to deal with buffers and streams instead of strings. In some cases this can be good, but mostly there is no point. If you have IIS 8 on server why bother with this library if you can use SignalR, which will take care most of the stuff for you.windows
I think this is more of proof-of-concept then usable library.瀏覽器
int count = receiveResult.Count; while (receiveResult.EndOfMessage == false) { if (count >= maxMessageSize) { string closeMessage = string.Format("Maximum message size: {0} bytes.", maxMessageSize); await socket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); return; } receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer, count, maxMessageSize - count), CancellationToken.None); count += receiveResult.Count; } var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count); var echoString = "You said " + receivedString; ArraySegment outputBuffer = new ArraySegment(Encoding.UTF8.GetBytes(echoString)); await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None); SuperWebsocket http://superwebsocket.codeplex.com/ 最後但並非最不重要的是SuperWebsocket。我對這個有一點懷疑(若是我沒記錯的話,這僅僅是一個我經過NuGet網站發現的包,但又不是一個可用的包)。它彷佛有一點複雜,但實際上它是很是簡單的。有文獻支持的例子幫助你一步步的從最簡單的WebSocket服務器,到有命令請求,JSON,多服務器實例,.config文件配置或者更多的複雜Websocket服務器。 這個庫也許沒有包含全部其餘庫有的那些很酷的特性,可是這不要緊,由於它是高度可配置的,你能夠很容易的讓它實現你想要的。它能夠做爲控制檯應用程序或者windows服務運行於ASP.NET中。文獻上則建議以系統服務的形式來運行服務器。從個人經驗來看,建議不要在一個web應用程序裏面運行它由於這種解決方案很慢(很是糟糕的表現,比控制檯應用程序大約慢50倍)。從另外一方面,獨立的服務器應用程序,須要運行.exe結尾的文件,這個文件並非庫的一部分,可是是SuperSocket項目的一部分(SuperWebSocket就是基於這個項目的)。這使得你須要一點技巧在調試會話中開啓服務器,或者徹底啓用調試。當你做爲應用程序運行服務器的時候,雖然這不是解決方案的一部分,也須要確保服務器採用來自其餘項目的最新版的組件。 做爲回報,你獲得了關於靈活的WebSocket的衆所周知的解決方案。 它仍然是開源的因此你能夠根據須要改變它。 從另外一方面,你可能把這個服務器缺少JavaScript客戶端看作是它的缺點(可是它有C#客戶端)。這個服務器也有第三方的依賴關係。 在使用這個庫工做了幾個月以後我沒發現什麼主要的問題。 缺點和優勢: • 無備用通訊 • 依賴 • 優雅的特性和高度可配置性 • 很棒的例子 • 例子的都有推薦設置的文檔 • 能夠做爲windows服務和ASP.NET模塊和控制檯應用程序運行 • 好的性能表現 總結 對於複雜的解決方案/項目建議用SuperWebSocket,由於它是一個穩定並且高度可配置的庫。對於簡單和須要快速開發的項目我會選擇Fleck,可是若是有辦法使用最新的windows服務器來做爲測試和生產機器的話,建議放棄使用這兩個而選擇SignalR。